1.信号量的概念。 信号量的本质是一种数据操作锁,它本⾝身不具有数据交换的功能,而是通过控制其他的通信资源(文件,外部设备)来实现进程间通信,它本⾝身只是一种外部资源的标识。信号量在此过程中负责数据操作的互斥、同步等功能。 当请求一个使用信号量来表示的资源时,进程需要先读取信号量的值来判断资源是否可用。大于0,资源可以请求,等于0,无资源可用,进程会进⼊入睡眠状态直至资源可用。 当进程不再使用一个信号量控制的共享资源时,信号量的值+1,对信号量的值进行的增减 操作均为原子操作,这是由于信号量主要的作用是维护资源的互斥或多进程的同步访问。 而在信号量的创建及初始化上,不能保证操作均为原子性。 2.信号量是如何工作的 由于信号量只能进⾏行两种操作等待和发送信号,即P(sv)和V(sv),他们的⾏行为是这样的: P(sv):如果sv的值⼤大于零,就给它减1;如果它的值为零,就挂起该进程的执⾏行 V(sv):如果有其他进程因等待sv⽽而被挂起,就让它恢复运⾏行,如果没有进程因等待sv⽽而挂 起,就给它加1. 3.相关函数 函数原型:int semget(key_t key,int nsems,int semflg); 参数解释: key:所创建或打开信号量集的键值。需要是唯一的非零整数。 nsems:创建的信号量集中的信号量的个数,该参数只在创建信号量集时有效。几乎总是取值为1. flag:调用函数的操作类型,也可用于设置信号量集的访问权限,用或来表示。
功能描述 获取与某个键关联的信号量集标识。信号量集被建立的情况有两种: 1.如果键的值是ipC_PRIVATE。 2.或者键的值不是IPC_PRIVATE,并且键所对应的信号量集不存在,同时标志中指定IPC_CREAT。 当调用semget创建一个信号量时,他的相应的semid_ds结构被初始化。ipc_perm中各个量被设置为相应 值: sem_nsems被设置为nsems所示的值; sem_otime被设置为0; sem_ctime被设置为当前时间。 函数原型:int semop( int semid, struct sembuf semoparray[], size_t nops ); 参数解释: 参数semid是一个通过semget函数返回的一个信号量标识符 参数nops标明了参数semoparray所指向数组中的元素个数 参数semoparray是一个struct sembuf结构类型的数组指针, 结构sembuf来说明所要执行的操作,其成员如下: 其中sem_flg说明函数semop的行为。通常被设置为SEM_UNDO。它将使得操作系统跟着当前进程对这个信号量的修改情况,如果这个进程在没有释放该信号量的情况下终止,操作系统将自动释放该进程持有的信号量。
函数原型:int semctl(int semid,int semnum,int cmd,…); 参数解释: sem_id是由semget返回的信号量标识符。 sem_num与前面一个函数相同。 cmd:表示将要采取的动作。 如果有第四个参数,一般为联合体semun,成员如下:
信号量使用的简单示例: 我们创建一个进程,代码如下:
#include"head.h"#include<unistd.h>#include<sys/wait.h>int main(){ int sem_id = my_semget(1); initial(sem_id, 0); pid_t id = fork();//创建一个子进程 if (0 == id){ while(1){ //上锁 if ( sem_p(sem_id, 0) == -1){ perror("children p error"); exit(0); } usleep(10200); printf("A"); fflush(stdout); usleep(23043); printf("A"); fflush(stdout); if ( sem_v(sem_id,0) == -1){ perror("children v error"); exit(0); } } } else{ while(1){ //上锁 if ( sem_p(sem_id, 0) == -1){ perror("father p error"); exit(0); } usleep(10200); usleep(16200); printf("B"); fflush(stdout); usleep(33043); printf("B"); fflush(stdout); if ( sem_v(sem_id,0) == -1){ perror("father v error"); exit(0); } } int stat = 0; wait(&stat); }}在没有信号量之前,因为有睡眠延时,系统会随机打印A和B,如: 添加信号量之后,因为A进程在信号量上锁后,sv值变为0,则B进程会挂起,直到A进程解锁,则系统会有规律的打印A和B。
新闻热点
疑难解答