赞
踩
信号量相当于钥匙,进程A拿钥匙进入临界资源(多个进程都可以进入),B就没有钥匙进去了,只能A出来,B才有钥匙拿进去。
信号量(semaphore)与已经介绍过的 IPC 结构不同,它是一个计数器。信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。
原子操作:就是在执行某一操作时不被打断。
linux原子操作问题来源于中断、进程的抢占以及多核smp系统中程序的并发执行。
最简单的信号量是只能取 0 和 1 的变量,这也是信号量最常见的一种形式,叫做二值信号量(Binary Semaphore)。而可以取多个正整数的信号量被称为通用信号量。
Linux 下的信号量函数都是在通用的信号量数组上进行操作,而不是在一个单一的二值信号量上进行操作。
- 1 #include <sys/sem.h>
-
- // 创建或获取一个信号量组:若成功返回信号量集ID,失败返回-1
- 2 int semget(key_t key, int num_sems, int sem_flags); 创建信号量
- 参数1 :key
- 参数2: 信号量集当中的信号量个数 (1)
- 参数3: (创建/获取) IPC_CREAT|0666
- 返回值:集合id
-
- // 对信号量组进行操作,改变信号量的值:成功返回0,失败返回-1
- 3 int semop(int semid, struct sembuf semoparray[], size_t numops);
- 参数1:semid
- 参数2: 次参数的数组可以在结构体进行
- 参数3: SEM_UNDO (默认)t
-
-
-
- void getkey(int id){
- struct sembuf set;
- set.sem_num =0; /* Operate on semaphore 0 */
- set.sem_op =-1; / * Wait for value to equal 0 */
- set.sem_flg = SEM_UNDO;
- semop(id,&set,1);
- printf("get the key\n");
- }
-
- void backkey(int id){
- struct sembuf set;
- set.sem_num =0; /* Operate on semaphore 0 */
- set.sem_op =1; /* Wait for value to equal 0 */
- set.sem_flg = SEM_UNDO;
- semop(id,&set,1);
- printf("back the key\n");
- }
-
-
-
- // 控制信号量的相关信息
- 4 int semctl(int semid, int sem_num, int cmd, ...); 初始化信号量
- 参数1:返回值信号量集合id
- 参数2:操作第几个信号量
- 参数3:(设置信号量的值)SETVAL
- 参数4: 一个结构体 (结构体的第一个数据提前初始化)

先实现一段代码
- 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) */
- };
-
-
-
- void getkey(int id){
- struct sembuf set;
- set.sem_num =0; /* Operate on semaphore 0 */
- set.sem_op =-1; /* Wait for value to equal 0 */
- set.sem_flg = SEM_UNDO;
- semop(id,&set,1);
- printf("get the key\n");
- }
-
- void backkey(int id){
- struct sembuf set;
- set.sem_num =0; /* Operate on semaphore 0 */
- set.sem_op =-1; /* Wait for value to equal 0 */
- set.sem_flg = SEM_UNDO;
- semop(id,&set,1);
- printf("get the key\n");
- }
-
- void backkey(int id){
- struct sembuf set;
- set.sem_num =0; /* Operate on semaphore 0 */
- set.sem_op =1; /* Wait for value to equal 0 */
- set.sem_flg = SEM_UNDO;
- semop(id,&set,1);
- printf("back the key\n");
- }
-
- int main(){
-
- union semun data;
- key_t key;
- key=ftok(".",'1');
- int semid =semget(key,1,IPC_CREAT|0666); //创建
- data.val=0; //这个值关乎信息量钥匙的有与没,拿与放
- semctl(semid, 0, SETVAL,data.val); //初始化 信息量
-
- pid_t pid=fork();
-
- if(pid>0){
-
- getkey(semid); //获取钥匙
- printf("the is father\n");
- backkey(semid); //退出钥匙
- }
- else if (pid==0){
- // getkey(semid);
- printf("the is chill\n");
- backkey(semid);
- }
- else{
- printf(" open pid error\n");
- }
- return 0;
- }
-
-

运行
- CLC@Embed_Learn:~/ccc$ ./sig
- the is chill
- back the key
- get the key
- the is father
- back the key
- CLC@Embed_Learn:~/ccc$ vi demo17.c
上面的例子如果不加信号量,则子进程会先执行完毕。这里加了信号量让子进程等待父进程执行完以后再执行。
更详细的代码参考
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。