一、什么是信号量?
信号量的本质就是计数器,记录临界资源的数目,用来协助进程同步互斥的访问临界资源。为什么不在进程中定义一个全局变量作为计数器呢?两个进程间的地址空间是各自独立的,各自有各自的虚拟内存空间。多进程之间不能看到各自进程中的全局变量。(进程间的虚拟内存https://blog.youkuaiyun.com/jane_yao/article/details/81635979)既然多个进程都能对信号量进行操作,那信号量本身也是临界资源。
因为信号量本身也是临界资源,所以对信号量的增加减少操作是原子的PV操作(不可中断的)。
二、信号量的操作
systemV版本的信号量申请时是以信号量集为单位申请的 ,P操作为申请资源(资源数目减一)V操作释放资源(资源数目加一)申请不到资源就挂起等待。
1.创建: int semget(key_t key, int nsems, int semflg)
参数1key用ftok获取key_t ftok(const char *pathname, int proj_id)参数2所申请信号量集中的元素的个数,最少申请一个参数3为创建IPC_CREAT | IPC_EXCL。返回值是创建的信号集标号。
2.初始化/删除:初始化和删除都是用的是 int semctl(int semid, int semnum, int cmd, ...);
参数1对标号semid的信号集操作,参数2信号集中下标为semnum的信号量进行设置,参数三创建时使用SETVAL删除时就直接使用IPC_RMID,初始化时有可变参数初始化就自己定义联合体
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */
};SETVAL)
其中int val表示初始化时设置为几。
3.PV操作:int semop(int semid, struct sembuf *sops, unsigned nsops);
参数1对标号semid的信号量集进行操作,参数2信号量集中可能有多个信号量所以使用了系统自带的结构体sembuf
系统自带的sembuf的内容为
unsigned short sem_num; /* semaphore number */ //对哪个信号量进行操作 ,信号量在数组中的下标
short sem_op; /* semaphore operation */ //-1为P操作1为V操作
short sem_flg; /* operation flags */ //默认设置为0
参数3信号操作结构的数量,就是1
三、使用函数创建二元信号量实现互斥锁
创建两个进程,子进程打印C父进程打印P
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <sys/types.h>
4 #include <sys/ipc.h>