linux进程间信号量

Linux 提供的各种系统调用来实现一个具有两种状态的信号量(binary semaphore)。

分配和释放

  和用于分配、释放共享内存的 shmget 和 shmctl 类似,系统调用 semget 和 semctl 负责分配、释放信号量。调用 semget 函数并传递如下参数:一个用于标识信号量组的键值,该组中包含的信号量数量和与 shmget 所需的相同的权限位标识。该函数返回的是信号量组的标识符。您可以通过指定正确的键值来获取一个已经存在的信号量的标识符;这种情况下,传递的信号量组的容量可以为0。
  信号量会一直保存在系统中,甚至所有使用它们的进程都退出后也不会自动被销毁。最后一个使用信号量的进程必须明确地删除所使用的信号量组,来确保系统中不会有太多闲置的信号量组,从而导致无法创建新的信号量组。可以通过调用semctl来删除信号量组。调用时的四个参数分别为信号量组的标识符,组中包含的信号量数量、常量 IPC_RMID 和一个 union semun 类型的任意值(被忽略)。调用进程的有效用户 id 必须与分配这个信号量组的用户 id 相同(或者调用进程为 root 权限亦可)。与共享内存不同,删除一个信号量组会导致 Linux 立即释放资源。
  代码 5.2 展示了用于分配和释放一个二元信号量的函数。
  代码 5.2 (sem_all_deall.c)分配和释放二元信号量
  #include <sys/ipc.h> #include <sys/sem.h> #include <sys/types.h> /* 我们必须自己定义 semun 联合类型。 */ union semun { int val; struct semid_ds *buf; unsigned short int *array; struct seminfo *__buf; }; /* 获取一个二元信号量的标识符。如果需要则创建这个信号量 */ int binary_semaphore_allocation (key_t key, int sem_flags) { return semget (key, 1, sem_flags); } /* 释放二元信号量。所有用户必须已经结束使用这个信号量。如果失败,返回 -1 */ int binary_semaphore_deallocate (int semid) { union semun ignored_argument; return semctl (semid, 1, IPC_RMID, ignored_argument); }

初始化信号量

  分配与初始化信号量是两个相互独立的操作。以 0 为第二参数,以 SETALL 为第三个参数调用 semctl 可以对一个信号量组进行初始化。第四个参数是一个 semun 对象,且它的 array 字段指向一个 unsigned short 数组。数组中的每个值均用于初始化该组中的一个信号量。
  代码 5.3 展示了初始化一个二元信号量的函数。
  代码 5.3 (sem_init.c) 初始化一个二元信号量
  #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> /* 我们必须自己定义 union semun。*/ union semun { int val; struct semid_ds *buf; unsigned short int *array; struct seminfo *__buf; }; /* 将一个二元信号量初始化为 1。*/ int binary_semaphore_initialize (int semid) { union semun argument; unsigned short values[1]; values[0] = 1; argument.array = values; return semctl (semid, 0, SETALL, argument); }

等待和投递操作

  每个信号量都具有一个非负的值,且信号量支持等待和投递操作。系统调用 semop 实现了这两个操作。它的第一个参数是信号量的标识符,第二个参数是一个包含 struct sembuf 类型元素的数组;这些元素指明了您希望执行的操作。第三个参数是这个数组的长度。 结构体sembuf中包含如下字段:
  sem_num将要执行操作的信号量组中包含的信号量数量。 sem_op是一个指定了操作类型的整数。 如果sem_op是一个正整数,则这个值会立刻被加到信号量的值上。 [BR]如果 sem_op 为负,则将从信号量值中减去它的绝对值。如果这将使信号量的值小于零,则这个操作会导致进程阻塞,直到信号量的值至少等于操作值的绝对值(由其它进程增加它的值)。 [BR]如果 sem_op 为0,这个操作会导致进程阻塞,直到信号量的值为零才恢复。 sem_flg 是一个符号位。指定 IPC_NOWAIT 以防止操作阻塞;如果该操作本应阻塞,则semop调用会失败。如果为sem_flg指定SEM_UNDO,Linux会在进程退出的时候自动撤销该次操作。 代码 5.4 展示了二元信号量的等待和投递操作。
  代码 5.4 (sem_pv.c)二元信号量等待和投递操作
  #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> /* 等待一个二元信号量。阻塞直到信号量的值为正,然后将其减1 */ int binary_semaphore_wait (int semid) { struct sembuf operations[1]; /* 使用(且仅使用)第一个信号量 */ operations[0].sem_num = 0; /* 减一。 */ operations[0].sem_op = -1; /* 允许撤销操作 */ operations[0].sem_flg = SEM_UNDO; return semop (semid, operations, 1); } /* 对一个二元信号量执行投递操作:将其值加一。 这个操作会立即返回。*/ int binary_semaphore_post (int semid) { struct sembuf operations[1]; /* 使用(且仅使用)第一个信号量 */ operations[0].sem_num = 0; /* 加一 */ operations[0].sem_op = 1; /* 允许撤销操作 */ operations[0].sem_flg = SEM_UNDO; return semop (semid, operations, 1); } 指定 SEM_UNDO 标志解决当出现一个进程仍然持有信号量资源时被终止这种特殊情况时可能出现的资源泄漏问题。当一个进程被有意识或者无意识地结束的时候,信号量的值会被调整到“撤销”了所有该进程执行过的操作后的状态。例如,如果一个进程在被杀死之前减小了一个信号量的值,则该信号量的值会增长。

调试信号量

  命令 ipcs -s 可以显示系统中现有的信号量组的相关信息。而 ipcrm sem 命令可以从命令行删除一个信号量组。例如,要删除标识符为5790517的信号量组则应运行以下命令:
  % ipcrm sem 5790517

linux进程间信号量相关推荐

  1. linux共享内存示例,linux 进程间共享内存示例

    写入端: #include #include #include #include #include using namespace std; struct MappingDataType { int ...

  2. Linux 进程间通讯(IPC)方式 ------- 共享内存

    Linux 进程间通讯(IPC)方式有以下几种: 1->管道(pipe)和有名管道(fifo). 2->消息队列 3->共享内存 4->信号量 5->信号(signal) ...

  3. Linux 进程间通讯方式 pipe()函数

    Linux 进程间通讯方式有以下几种: 1->管道(pipe)和有名管道(fifo). 2->消息队列 3->共享内存 4->信号量 5->信号(signal) 6-&g ...

  4. linux无名管道实验代码,Linux 进程间通讯之创建无名管道和读写无名管道

    Linux进程间通讯的方式: 1. 管道(pipe)和有名管道(FIFO). 2. 信号(signal) 3. 消息队列 4. 共享内存 5. 信号量 6. 套接字(socket) 管道通讯: 无名管 ...

  5. 深刻理解 Linux 进程间七大通信(IPC)

    前言 网络编程是 Linux C/C++的面试重点,今天我就来聊一聊进程间通信的问题,文章末尾列出了参考资料,希望帮助到大家. 篇幅有点长,希望大家耐心阅读. Linux 下的进程通信手段基本上是从 ...

  6. msgget();msgsnd();msgrcv();msgctl(); 消息队列 Linux进程间的通信方式之消息队列

    Linux进程间的通信方式 ----消息队列. 消息队列和共享内存类似 消息队列它允许一个或多个进程向它写消息,一个或多个进程向它写读消息. 消息队列存在于系统内核中,消息的数量受系统限制. 我们来看 ...

  7. linux进程间通讯-信号

    文章目录 进程间通信功能 信号 信号的概念 产生信号的方式 信号的默认(缺省)处理方式 进程接收到信号后的处理方式 kill函数 alarm函数 raise函数 abort函数 pause函数 sig ...

  8. Linux进程间通讯

    最初Unix IPC包括:管道.FIFO.信号: System V IPC包括:System V消息队列.System V信号灯.System V共享内存区: Posix IPC包括: Posix消息 ...

  9. Linux进程间通讯之消息队列

    首先有个大体的概念:http://www.xefan.com/archives/83703.html 头文件: #include <sys/ipc.h> #include <sys/ ...

最新文章

  1. 基于 Python 环境搭建 - YOLO 实现吸烟行为监测
  2. 机械转行的都干啥去了?机械转行计算机难吗?
  3. 休斯顿大学提出BCI-机器人(脑-外骨骼接口系统)可以改善运动恢复
  4. Java快速判断是不是手机号
  5. upc组队赛5 Bulbs
  6. 如何在 C#9 中使用 static 匿名函数
  7. 第六届省赛(软件类)真题----Java大学C组答案及解析
  8. 【LeetCode 剑指offer刷题】树题19:8 二叉树中序遍历的下一个结点
  9. 精选 | 2018年3月R新包推荐
  10. taro 请务必在小程序页面中完善页面基础信息_如何一人五天开发完复杂微信小程序...
  11. 为什么JavaScript声明变量的时候鼓励加var关键字
  12. 2021-09-07LFM(latent factor model)
  13. matlab 图像 变成二维,matlab三维图像变二维
  14. wow插件入门资源整理
  15. 梯度下降算法和逆误差传播算法
  16. 深度:企业为什么需要一个平台级的OA产品?
  17. IDEA插件系列(94):Pomodoro-tm插件——番茄钟计时
  18. 0X000000该内存不能为read的解决方法(转)
  19. CORS请求的简单请求和非简单请求
  20. Ubuntu 18.04安装Docker Dashboard

热门文章

  1. LLM系列 | 01: 亲测ChatGPT最强竞品Claude,且无需翻墙、注册简单、免手机号
  2. 801-分享“入选腾讯犀牛鸟精英营”心得
  3. 佛罗里达州的最新的野生动物保护区
  4. [转]Java咖啡馆---叹咖啡
  5. 在线TSV转SQL工具
  6. 【Unity】基础游戏单位GameObject中常用的属性和API
  7. 求解线性方程组的方法Matlab程序
  8. 基于ES7243E ADC芯片I2S接口在BES平台上LINE-IN驱动开发
  9. c#qq群 群号:11069698 欢迎喜欢和爱好c#的朋友加入!
  10. 宝塔Linux面板登录的账号密码忘了怎么办?