对信号量P/V操作以及共享资源的使用

编程入门 行业动态 更新时间:2024-10-05 03:20:42

对<a href=https://www.elefans.com/category/jswz/34/1769130.html style=信号量P/V操作以及共享资源的使用"/>

对信号量P/V操作以及共享资源的使用

共享内存(SHM)    共享内存是效率最高的 IPC,因为他抛弃了内核这个“代理人”,直截了当地将一块裸 露的内存放在需要数据传输的进程面前,让他们自己搞,这样的代价是:这些进程必须小心 谨慎地操作这块裸露的共享内存,做好诸如同步、互斥等工作,毕竟现在没有人帮他们来管 理了,一切都要自己动手。也因为这个原因,共享内存一般不能单独使用,而要配合信号量、 互斥锁等协调机制,让各个进程在高效交换数据的同时,不会发生数据践踏、破坏等意外。 共享内存的思想很朴素,进程与进程之间虚拟内存空间本来相互独立,不能互相访问的, 但是可以通过某些方式,使得相同的一块物理内存多次映射到不同的进程虚拟空间之中,这 样的效果就相当于多个进程的虚拟内存空间部分重叠在一起,看示意图。

使用共享内存的一般步骤是: 1 ,获取共享内存对象的 ID 2 ,将共享内存映射至本进程虚拟内存空间的某个区域 3 ,当不再使用时,解除映射关系 4 ,当没有进程再需要这块共享内存时,删除它 信号量(SEM) 信号量 SEM全称 Semaphore,中文也翻译为信号灯。作为system-V IPC 的最后一种,信号量跟前面的 MSG 和 SHM 有极大的不同, SEM 不是用来传输数据的, 而是作为“旗语”,用来协调各进程或者线程工作的。 一些基本概念如下:         1 ,多个进程或线程有可能同时访问的资源(变量、链表、文件等等)称为共享资源, 也叫临界资源(critical resources)。         2 ,访问这些资源的代码称为临界代码,这些代码区域称为临界区(critical zone)。         3 ,程序进入临界区之前必须要对资源进行申请,这个动作被称为 P 操作,这就像你要 把车开进停车场之前,先要向保安申请一张停车卡一样, P 操作就是申请资源,如果申请成 功,资源数将会减少。如果申请失败,要不在门口等,要不走人。         4 ,程序离开临界区之后必须要释放相应的资源,这个动作被称为 V 操作,这就像你把 车开出停车场之后,要将停车卡归还给保安一样, V 操作就是释放资源,释放资源就是让资 源数增加。          所有一起访问共同临界资源的进程都必须遵循以上游戏规则,否则大家就都乱套了,但 是值得注意的是:这些规则是自愿的,如果有进程就是胡来——在访问资源之前不申请,那 么将会可能导致逻辑谬误,就像开车压死保安直接撞进停车场一样,虽然于情于理都不可以, 物理上阻止不了这种行为。                   system-V 的信号量非常类似于停车场的卡牌,想象一个有 N 个车位的停车场,每个 车位是立体的可升降的,能停 n 辆车,那么我们可以用一个拥有 N 个信号量元素,每个信 号量元素的初始值等于 n 的信号量来代表这个停车场的车位资源——某位车主要把他的 m 辆车开进停车场,如果需要 1 个车位,那么必须对代表这个车位的信号量元素申请资源, 如果 n 大于等于 m ,则申请成功,否则不能把车开进去。

  对 于共享内存和信号量的使用 

发送端代码如下jack.c

#include<stdio.h>
#include <sys/types.h> 
#include <sys/shm.h>#include <sys/ipc.h> #include <sys/sem.h>#include <unistd.h>#include <stdlib.h>union semun
{int val;                 /* 当 cmd 为 SETVAL 时使用 */ struct semid_ds *buf;    /* 当 cmd 为 IPC_STAT 或 IPC_SET 时使用 */unsigned short *array;   /* 当 cmd 为 GETALL 或 SETALL 时使用 */struct seminfo *__buf;   /* 当 cmd 为 IPC_INFO 时使用 */
};char * shm_init()
{//获取KEY值int key=ftok("./",'K');int shm_id=shmget(key, 4096,IPC_CREAT|0666);if(shm_id==-1){perror("shmget id erorr");exit(1);//直接结束进程}//映射共享内存char *shm_map=shmat(shm_id, NULL, 0);if(shm_map==(void *)-1){perror("shm map error");exit(1);//直接结束进程}return shm_map;}int sem_init()
{//获取新的KEY值int key=ftok("./",'X');//获取信号量的IDint sem_id=semget(key, 2, IPC_CREAT|0644);if(sem_id==-1){perror("sem get id error ");exit(1);}//初始化信号量的内容 主要是初始化他们的初始化的资源数//初始化没有数据,有一个空间union semun set;set.val=0;   semctl(sem_id, 0, SETVAL, set);   //0 初始化数据资源set.val=1; semctl(sem_id, 1, SETVAL,set );  //1 初始化空间资源return sem_id;
}int main(int argc, char const *argv[])
{//配置共享内存并初始化char *shm_map=shm_init();//初始化信号量int  sem_id=sem_init();//再写入共享内存之前需要现申请一个空间资源/* struct sembuf { unsigned short sem_num;     /* 信号量元素序号(数组下标) short sem_op;               /* 操作参数 *short sem_flg;              /* 操作选项 };*/struct sembuf space={     //设置空间资源 .sem_num=1,          //需要设置的空间资源元素下表为1.sem_flg=0,          //设置标记为0 啥也不选.sem_op=-1           //-1表示资源量即将建议  申请资源};struct sembuf data={     //设置空间资源 .sem_num=0,          //需要设置的空间资源元素下表为0.sem_flg=0,          //设置标记为0 啥也不选.sem_op=1           //1表示资源量即将加1  释放资源};while (1){//等待空间资源  会阻塞 如果资源暂时不能得到则会阻塞等待semop(sem_id,  &space, 1);printf("请输入需要发送的数据\n"); fgets(shm_map,4096,stdin);//设置数据资源为1 semop(sem_id,  &data, 1);/* code */}return 0;
}
接收端代码 rocs.c
#include<stdio.h>
#include <sys/types.h> 
#include <sys/shm.h>#include <sys/ipc.h> #include <sys/sem.h>#include <unistd.h>#include <stdlib.h>union semun
{int val;                 /* 当 cmd 为 SETVAL 时使用 */ struct semid_ds *buf;    /* 当 cmd 为 IPC_STAT 或 IPC_SET 时使用 */unsigned short *array;   /* 当 cmd 为 GETALL 或 SETALL 时使用 */struct seminfo *__buf;   /* 当 cmd 为 IPC_INFO 时使用 */
};char * shm_init()
{//获取KEY值int key=ftok("./",'K');int shm_id=shmget(key, 4096,IPC_CREAT|0666);if(shm_id==-1){perror("shmget id erorr");exit(1);//直接结束进程}//映射共享内存char *shm_map=shmat(shm_id, NULL, 0);if(shm_map==(void *)-1){perror("shm map error");exit(1);//直接结束进程}return shm_map;}int sem_init()
{//获取新的KEY值int key=ftok("./",'X');//获取信号量的IDint sem_id=semget(key, 2, IPC_CREAT|0644);if(sem_id==-1){perror("sem get id error ");exit(1);}//初始化信号量的内容 主要是初始化他们的初始化的资源数//初始化没有数据,有一个空间union semun set;set.val=0;   semctl(sem_id, 0, SETVAL, set);   //0 初始化数据资源set.val=1; semctl(sem_id, 1, SETVAL,set );  //1 初始化空间资源return sem_id;
}int main(int argc, char const *argv[])
{//配置共享内存并初始化char *shm_map=shm_init();//初始化信号量int  sem_id=sem_init();//再写入共享内存之前需要现申请一个空间资源/* struct sembuf { unsigned short sem_num;     /* 信号量元素序号(数组下标) short sem_op;               /* 操作参数 *short sem_flg;              /* 操作选项 };*/struct sembuf space={     //设置空间资源 .sem_num=1,          //需要设置的空间资源元素下表为1.sem_flg=0,          //设置标记为0 啥也不选.sem_op=1           //1表示资源量即将加以  释放资源};struct sembuf data={     //设置空间资源 .sem_num=0,          //需要设置的空间资源元素下表为0.sem_flg=0,          //设置标记为0 啥也不选.sem_op=-1          //1表示资源量即将加1  释放资源};while (1){printf("wait 数据\n");//等待数据资源  会阻塞 如果资源暂时不能得到则会阻塞等待semop(sem_id,  &data, 1);printf("Jacl 说:%s\n",shm_map);//设置空间资源为1 semop(sem_id,  &space, 1);/* code */}return 0;
}

更多推荐

对信号量P/V操作以及共享资源的使用

本文发布于:2024-02-28 08:06:18,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1768721.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:信号量   共享资源   操作

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!