王朝百科
分享
 
 
 

linux进程间信号量

王朝百科·作者佚名  2010-08-25  
宽屏版  字体: |||超大  

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

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
如何用java替换看不见的字符比如零宽空格&#8203;十六进制U+200B
 干货   2023-09-10
网页字号不能单数吗,网页字体大小为什么一般都是偶数
 干货   2023-09-06
java.lang.ArrayIndexOutOfBoundsException: 4096
 干货   2023-09-06
Noto Sans CJK SC字体下载地址
 干货   2023-08-30
window.navigator和navigator的区别是什么?
 干货   2023-08-23
js获取referer、useragent、浏览器语言
 干货   2023-08-23
oscache遇到404时会不会缓存?
 干货   2023-08-23
linux下用rm -rf *删除大量文件太慢怎么解决?
 干货   2023-08-08
刀郎新歌破世界纪录!
 娱乐   2023-08-01
js实现放大缩小页面
 干货   2023-07-31
生成式人工智能服务管理暂行办法
 百态   2023-07-31
英语学习:过去完成时The Past Perfect Tense举例说明
 干货   2023-07-31
Mysql常用sql命令语句整理
 干货   2023-07-30
科学家复活了46000年前的虫子
 探索   2023-07-29
英语学习:过去进行时The Past Continuous Tense举例说明
 干货   2023-07-28
meta name="applicable-device"告知页面适合哪种终端设备:PC端、移动端还是自适应
 干货   2023-07-28
只用css如何实现打字机特效?
 百态   2023-07-15
css怎么实现上下滚动
 干货   2023-06-28
canvas怎么画一个三角形?
 干货   2023-06-28
canvas怎么画一个椭圆形?
 干货   2023-06-28
canvas怎么画一个圆形?
 干货   2023-06-28
canvas怎么画一个正方形?
 干货   2023-06-28
中国河南省郑州市金水区蜘蛛爬虫ip大全
 干货   2023-06-22
javascript简易动态时间代码
 干货   2023-06-20
感谢员工的付出和激励的话怎么说?
 干货   2023-06-18
 
>>返回首页<<
 
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有