linux进程通信——信号量


1.     信号量

(1)概念

信号量(又名:信号灯)与其他进程间通信方式不大相同,主要用途是保护临界资源.

进程可以根据它判定是否能够访问某些共享资源。除了用于访问控制外,还可用于进程同步。

(2)分类

二值信号灯:信号灯的值只能取0或1,类似于互斥锁。 但两者有不同:

信号灯强调共享资源,只要共享资源可用,其他进程同样可以修改信号灯的值;

互斥锁更强调进程,占用资源的进程使用完资源后,必须由进程本身来解锁。

   计数信号灯:信号灯的值可以取任意非负值

(3)步骤

a)       创建打开信号量,semget()

b)       初始化信号量,semctl()SETVAL操作。使用二维信号量时将信号量初始化为1;

c)       进行信号量的PV操作,调用semop()函数。

d)       如果不用信号量,从系统中删除他/她,使用semctl的IPC_RMID操作。

 

2.     内核实现信号灯的原理及其API函数

(1)semget

函数的作用:创建信号量

函数的原型:int semget(key_t key,int nsems,int semflg);

函数的参数:nsems:创建信号量的数目,通常取1个

            semflg:同open一样的权限

返回值:成功:信号量的标识符;出错:-1

(2)semctl

函数的作用:信号量的控制:初始化、删除等

函数的原型:int semctl(int semid,int semnum,int gmd,union semun arg);

函数的参数:semnum:通常为0,第一个信号量

            cmd:IPC_STAT:获取结构量

                IPC_SETVAL:设置为arg中的val值

                IPC_GETVAL:获取信号量的值

                IPC_RMID:从系统中删除信号量

            arg:union semun结构

返回值:cmd不同的返回值不同

    IPC_STAT、IPC_SETVAL、IPC_RMID、返回值为0;IPC_GETVAL:返回信号量的值;出错为-1

(3)semop

函数的作用:执行PV操作

函数的原型:int semop(int semid,struct sembuf * sops,size_t nsops);

函数的参数:semid:semget()函数返回的信号量标识符

            sops:指向信号量操作数组

            struct sembuf *sops;

            sem_op:-1为P操作;+1为V操作

            nsops:操作信号量的个数

返回值:成功:信号量标识符;出错:-1

 

3.     如何使用信号灯来实现进程间的同步与互斥?

信号量的同步和互斥PV(见下例)

sem1.c

[objc]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #include <stdlib.h>  
  4. #include <fcntl.h>  
  5. #include <sys/ipc.h>  
  6. #include <sys/sem.h>  
  7.   
  8. int main()  
  9. {  
  10.     int fd = 0;  
  11.     key_t key;  
  12.     int semid;  
  13.     struct sembuf sops;  
  14.     int ret;  
  15.   
  16.     key = ftok("/home/linux/"1);  
  17.     semid = semget(key, 1, IPC_CREAT);  
  18.   
  19.     ret = semctl(semid, 0, SETVAL, 1);  
  20.     fd = open("borad.txt", O_RDWR | O_CREAT | O_APPEND);  
  21.     sops.sem_num = 0;  
  22.     sops.sem_op = -1;  
  23.     semop(semid, &sops, 1);  
  24.   
  25.     write(fd, "class math"11);  
  26.   
  27.     sleep(20);  
  28.     sops.sem_num = 0;  
  29.     sops.sem_op = +1;  
  30.     semop(semid, &sops, 1);  
  31.     close(fd);  
  32.   
  33.     return 0;  
  34. }  

sem2.c

[objc]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #include <stdlib.h>  
  4. #include <fcntl.h>  
  5. #include <sys/ipc.h>  
  6. #include <sys/sem.h>  
  7.   
  8. int main()  
  9. {  
  10.     int fd = 0;  
  11.     key_t key;  
  12.     int semid;  
  13.     struct sembuf sops;  
  14.   
  15.     key = ftok("/home/linux/"1);  
  16.     semid = semget(key, 1, IPC_CREAT);  
  17.   
  18.     fd = open("borad.txt", O_RDWR | O_CREAT | O_APPEND);  
  19.     sops.sem_num = 0;  
  20.     sops.sem_op = -1;  
  21.     semop(semid, &sops, 1);  
  22.   
  23.     write(fd, "class math"11);  
  24.   
  25.     sleep(20);  
  26.     sops.sem_num = 0;  
  27.     sops.sem_op = +1;  
  28.     semop(semid, &sops, 1);  
  29.     close(fd);  
  30.   
  31.     return 0;  
  32. }  
运行结果:



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值