0
点赞
收藏
分享

微信扫一扫

linux进程间通信 -信号量

朱悟能_9ad4 2022-04-18 阅读 100
linux

信号量

由于信号量只能进行两种操作等待和发送信号,即P(sem)和V(sem)他们的行为是这样的:

  • P(sem):如果sem的值大于零,就给它减1;如果它的值为零,就挂起该进程的执行
  • V(sem):如果有其他进程因等待sem而被挂起,就让它恢复运行,如果没有进程因等待sv而挂起,就给它加1.

二元信号量(引用计数为1)

二元信号量(Binary Semaphore)是最简单的一种锁(互斥锁),

它只用两种状态:

  • sem = 0 挂起。
  • sem = 1,执行

创建信号量集

API

参数

key: 创建信号量的键值
nsems: 指定信号量集中需要的信号量数目,它的值几乎总是1
semflg:一组标志

返回值

成功: 信号量集的标识符
失败 : -1, 错误信息写入errno

错误代码

EACCES
密钥有一个信号集,但是调用进程没有访问该集的权限,并且在管理其IPC名称空间的用户名称空间中不具有CAP_IPC_OWNER功能。
EEXIST
在semflg中指定了IPC_CREAT和IPC_EXCL,但是密钥的信号量集已经存在。
EINVAL
nsems小于0或大于每个信号量集(SEMMSL)的信号量限制。
EINVAL
对应于key的信号量集已经存在,但是nsems大于该键集中的信号量。
ENOENT
没有为键设置信号量,并且semflg未指定IPC_CREAT。
ENOMEM
必须创建一个信号集,但是系统没有足够的内存来存储新的数据结构。
ENOSPC
必须创建一个信号集,但是将超出最大信号集集(SEMMNI)的系统限制或系统范围内最大信号量(SEMMNS)。

操作信号量

API

参数

semid:信号量集标识符
sops: 指向进行操作的信号量集结构体数组的首地址
nsops: 进行操作信号量的个数,即sops结构变量的个数,需大于或等于1。最常见设置此值等于1,只完成对一个信号量的操作

sembuf 结构体:

unsigned short sem_num;  /* semaphore number */
           short          sem_op;   /* semaphore operation */
           short          sem_flg;  /* operation flags */

sem_num : 信号在信号集中的索引,0代表第一个信号,1代表第二个信号
sem_op:信号量在一次操作中需要改变的数据,通常是两个数,

  • sem_op > 0 信号加上 sem_op 的值,表示进程释放控制的资源;
  • sem_op = 0 如果没有设置 IPC_NOWAIT,则调用进程进入睡眠状态,直到信号量的值不为0;否则进程不回睡眠,直接返回 EAGAIN
  • sem_op < 0 信号加上 sem_op 的值。若没有设置 IPC_NOWAIT ,则调用进程阻塞,直到资源可用;否则进程直接返回EAGAIN

sem_flg: IPC_NOWAIT and SEM_UNDO,如果操作指定SEM_UNDO,它将会自动撤消该进程终止时

当 sembuf 的第二个数据结构 sem_op 设置为负数时,是对它进行P操作,即减1操作;当设置为正数时,就是进行V操作,即加1操作。

返回值

成功: 信号量集的标识符
出错: -1,错误原因存于error中

错误代码

E2BIG:一次对信号量个数的操作超过了系统限制
EACCESS:权限不够
EAGAIN:使用了IPC_NOWAIT,但操作不能继续进行
EFAULT:sops指向的地址无效
EIDRM:信号量集已经删除
EINTR:当睡眠时接收到其他信号
EINVAL:信号量集不存在,或者semid无效
ENOMEM:使用了SEM_UNDO,但无足够的内存创建所需的数据结构
ERANGE:信号量值超出范围

删除和初始化信号量

API

参数

  • sem_id : semget返回的信号量标识符
  • semnum : 信号量集的哪一个信号量
  • cmd:
cmd说明
IPC_STAT从信号量集上检索semid_ds结构,并存到semun联合体参数的成员buf的地址中
IPC_SET设置一个信号量集合的semid_ds结构中ipc_perm域的值,并从semun的buf中取出值
IPC_RMID从内核中删除信号量集合
GETALL从信号量集合中获得所有信号量的值,并把其整数值存到semun联合体成员的一个指针数组中
GETNCNT返回当前等待资源的进程个数
GETPID返回最后一个执行系统调用semop()进程的PID
GETVAL返回信号量集合内单个信号量的值
GETZCNT返回当前等待100%资源利用的进程个数
SETALL与GETALL正好相反
SETVAL用联合体中val成员的值设置信号量集合中单个信号量的值
  • 第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) */
           };

semid_ds 结构体

       struct semid_ds {
           struct ipc_perm sem_perm;  /* Ownership and permissions */
           time_t          sem_otime; /* Last semop time */
           time_t          sem_ctime; /* Last change time */
           unsigned long   sem_nsems; /* No. of semaphores in set */
       };

返回值

成功:大于或等于0
出错: -1,错误原因存于error中

错误代码

EACCESS:权限不够
EFAULT:arg指向的地址无效
EIDRM:信号量集已经删除
EINVAL:信号量集不存在,或者semid无效
EPERM:进程有效用户没有cmd的权限
ERANGE:信号量值超出范围

举报

相关推荐

0 条评论