- 浏览: 144663 次
-
文章分类
最新评论
在XSI IPC通信之消息队列一节中我们介绍了消息队列,对比消息队列,本文将介绍信号量的一些常用操作。
信号量与管道、FIFO以及消息队列等IPC机制不同,它是一个用于为多进程提供对共享数据对象的访问的计数器。为了获得共享资源,进程需要执行下列操作。
(1)测试控制该资源的信号量。
(2)若此信号量的值为正,则进程可以使用该资源,并会将信号量的值减一,表示使用了一个资源单位。
(3)否则,若此信号量的值为0,则进程进入休眠状态,直到信号量值大于0才被唤醒,之后又会返回到步骤(1)。
当进程不再使用由一个信号量控制的共享资源时,该信号量值增 1,同时会唤醒正在等待此信号量的休眠进程。为了正确地实现信号量,信号量值的测试及加减操作都应当是原子操作,为此,信号量通常是在内核中实现的。
常用的信号量形式被称为二元信号量,它控制单个资源,其初始值为 1。但一般而言,信号量的初值可以是任意一个正值,表明有多少个共享资源单位可供共享应用。
不过,XSI 信号量与此相比要复杂得多。以下3种特性造成了这种不必要的复杂性。
(1)信号量并非是单个非负值,而必须定义为含有一个或多个信号量值的集合。当创建信号量时,要指定集合中信号量值的数量。
(2)信号量的创建是独立于它的初始化的。这是一个致命的缺点,因为不能原子地创建一个信号量集合,并且对该集合中的各个信号量值赋初值。
(3)即使没有进程正在使用各种形式的XSI IPC,它们仍然是存在的。有的程序在终止时并没有释放已经分配给它的信号量,后面要介绍的 undo 功能就是处理这种情况的。
下表列出了影响信号量集合的系统限制。
内核为每个信号量集合维护着一个 semid_ds 结构,一般至少包含下面这些字段。
每个信号量由一个无名结构表示,它至少包含下列成员。
在使用 XSI 信号量时,需要先调用 semget 函数来获得或创建一个信号量 ID。semctl 函数包含了多种信号量操作。semop 函数自动执行信号量集合上的操作数组。
使用 semget 函数创建一个新集合时,会对 semid_ds 结构的下列成员赋初值。
* 按XSI IPC 相似特征介绍一节中所述来初始化 ipc_perm 结构,该结构中的 mode 成员被设置为 flag 中的相应权限位。
* sem_otime 设置为 0。
* sem_ctime 设置为当前时间。
* sem_nsems 设置为 nsems。
参数 nsems 是该集合中的信号量数。如果是引用现有集合,可将其指定为 0。
semctl 函数的第 4 个参数是可选的,它的类型是 semun 联合体,是多个命令特定参数的联合,是否使用取决于所请求的命令。
cmd 参数指定下列 10 种命令中的一种,其中有 5 种是针对一个特定的信号量值的,它们用 semnum 指定该信号量集合中的一个成员。semnum 的值在 0 和 semget 函数的参数
nsems-1 之间。
* IPC_STAT:对此集合取 semid_ds 结构,并存储在由 arg.buf 指向的结构中。
* IPC_SET:按 arg.buf 指向的结构中的值,设置与此集合相关的结构中的 sem_perm.uid、sem_perm.gid 和 sem_perm.mode 字段。此命令只能由两种进程执行:一种是其有效用户 ID 等于 sem_perm.cuid 或 sem_perm.uid 的进程;另一种是具有超级用户特权的进程。
* IPC_RMID:从系统中立即删除该信号量集合。删除后其他进程在下次试图对此信号量集合进行操作时,将出错返回 EIDRM。该命令也只能由上面提及的两种进程执行。
* GETVAL:返回成员 semnum 的 semval 值。
* SETVAL:设置成员 semnum 的 semval 值为 arg.val 指定的值。
* GETPID:返回成员 semmum 的 sempid 值。
* GETNCNT:返回成员 semnum 的 semncnt 值。
* GETZCNT:返回成员 semnum 的 semzcnt 值。
* GETALL:取该集合中所有的信号量值,并存储在 arg.array 指向的数组中。
* SETALL:将该集合中所有的信号量值设置成 arg.array 指向的数组中的值。
对于除 GETALL 以外的所有 GET 命令,semctl 函数都返回相应值;对于其他命令,若成功则返回 0,否则返回 -1 并设置 errno。
semop 函数中的 semoparray 参数是一个由 sembuf 结构组成的信号量操作数组。nops 参数规定了该数组中操作的数量。对集合中每个成员的操作由 sembuf 结构中相应的 sem_op 值规定,它可以是负值、0 或正值,对各个情况的处理如下所述。
(1)sem_op 为正值:这对应于进程释放的占用的资源数。sem_op 值会加到信号量的值上。如果指定了 undo 标志(该标志对应于相应的 sem_flg 成员的 SEM_UNDO 位),则也从该进程的此信号量调整值中减去 sem_op。
(2)sem_op 为负值:这表示要获取由该信号量控制的资源。如若该信号量的值大于等于 sem_op 的绝对值(说明具有所需的资源),则从信号量值中减去 sem_op 的绝对值。如果指定了 undo 标志,则 sem_op 的绝对值也加到该进程的此信号量调整值上。如若信号量值小于 sem_op 的绝对值,则适用下列条件。
a)若指定了 IPC_NOWAIT,则 semop 函数出错返回 EAGAIN。
b)若未指定 IPC_NOWAIT,则该信号量的 semncnt 值加 1(因为调用进程将进入休眠),然后调用进程被挂起直至发生下列事件之一。
i. 此信号量值变成大于等于 sem_op 的绝对值(即某个进程已释放了某些资源)。此信号量的 semncnt 值减 1,并从信号量值中减去 sem_op 的绝对值。如果指定了 undo 标志,则 sem_op 的绝对值也加到该进程的此信号量调整值上。
ii. 从系统中删除了此信号量,此时 semop 函数出错返回 EIDRM。
iii. 进程捕捉到一个信号,并从信号处理程序返回。此时此信号量的 semncnt 值减 1(因为调用进程不再等待),并且 semop 函数出错返回 EINTR。
(3)sem_op 为 0:这表示调用进程希望等待到该信号量值变成 0。如果当前信号量值是 0,则 semop 函数立即返回。如果当前信号量值非 0,则适用下列条件。
a)若指定了 IPC_NOWAIT,则出错返回 EAGAIN。
b)若未指定 IPC_NOWAIT,则该信号量的 semzcnt 值加 1(因为调用进程将进入休眠),然后调用进程被挂起直至发生下列事件之一。
i. 此信号量值变成 0,此时会将此信号量的 semzcnt 值减 1。
ii. 从系统中删除了此信号量,此时 semop 函数出错返回 EIDRM。
iii. 进程捕捉到一个信号,并从信号处理程序返回。此时此信号量的 semzcnt 值减 1(因为调用进程不再等待),并且 semop 函数出错返回 EINTR。
semop 函数具有原子性,它或者执行数组中的所有操作,或者一个也不做。
前面说过,如果在进程终止时,它占用了经由信号量分配的资源,那么就会成为一个问题。无论何时只要为信号量操作指定了 SEM_UNDO 标志,然后分配资源(sem_op 值小于 0),那么内核就会记住对于该特定信号量,分配给调用进程多少资源(sem_op 的绝对值)。当该进程终止时,内核就会检验该进程是否还有尚未处理的信号量调整值,如果有,则按调整值对相应信号量进行处理。
如果用带有 SETVAL 或 SETALL 命令的 semctl 设置一个信号量的值,则在所有进程中,该信号量的调整值都将设置为 0。
信号量与管道、FIFO以及消息队列等IPC机制不同,它是一个用于为多进程提供对共享数据对象的访问的计数器。为了获得共享资源,进程需要执行下列操作。
(1)测试控制该资源的信号量。
(2)若此信号量的值为正,则进程可以使用该资源,并会将信号量的值减一,表示使用了一个资源单位。
(3)否则,若此信号量的值为0,则进程进入休眠状态,直到信号量值大于0才被唤醒,之后又会返回到步骤(1)。
当进程不再使用由一个信号量控制的共享资源时,该信号量值增 1,同时会唤醒正在等待此信号量的休眠进程。为了正确地实现信号量,信号量值的测试及加减操作都应当是原子操作,为此,信号量通常是在内核中实现的。
常用的信号量形式被称为二元信号量,它控制单个资源,其初始值为 1。但一般而言,信号量的初值可以是任意一个正值,表明有多少个共享资源单位可供共享应用。
不过,XSI 信号量与此相比要复杂得多。以下3种特性造成了这种不必要的复杂性。
(1)信号量并非是单个非负值,而必须定义为含有一个或多个信号量值的集合。当创建信号量时,要指定集合中信号量值的数量。
(2)信号量的创建是独立于它的初始化的。这是一个致命的缺点,因为不能原子地创建一个信号量集合,并且对该集合中的各个信号量值赋初值。
(3)即使没有进程正在使用各种形式的XSI IPC,它们仍然是存在的。有的程序在终止时并没有释放已经分配给它的信号量,后面要介绍的 undo 功能就是处理这种情况的。
下表列出了影响信号量集合的系统限制。

内核为每个信号量集合维护着一个 semid_ds 结构,一般至少包含下面这些字段。
struct semid_ds{ struct ipc_perm sem_perm; unsigned short sem_nsems; // # of semaphores in set time_t sem_otime; // last-semop() time time_t sem_ctime; // last-change time /* ... */ };
每个信号量由一个无名结构表示,它至少包含下列成员。
struct{ unsigned short semval; // semaphore value, always >= 0 pid_t sempid; // pid for last operation unsigned short semncnt; // # processes awaiting semval > curval unsigned short semzcnt; // # processes awaiting semval == 0 /* ... */ };
在使用 XSI 信号量时,需要先调用 semget 函数来获得或创建一个信号量 ID。semctl 函数包含了多种信号量操作。semop 函数自动执行信号量集合上的操作数组。
#include <sys/sem.h> int semget(key_t key, int nsems, int flag); /* 返回值:若成功,返回信号量ID;否则,返回-1 */ int semctl(int semid, int semnum, int cmd, .../* union semun arg */); /* 返回值:(见下面所述)*/ union semun{ int val; /* for SETVAL */ struct semid_ds *buf; /* for IPC_STAT and IPC_SET */ unsigned short *array; /* for GATALL and SETALL */ }; int semop(int semid, struct sembuf semoparray[], size_t nops); /* 返回值:若成功,返回 0;否则,返回-1 */ struct sembuf{ unsigned short sem_num; // member # in set (0, 1, ..., nsems-1) short sem_op; // operation (negative, 0, or pasitive) short sem_flg; // IPC_NOWAIT, SEM_UNDO };
使用 semget 函数创建一个新集合时,会对 semid_ds 结构的下列成员赋初值。
* 按XSI IPC 相似特征介绍一节中所述来初始化 ipc_perm 结构,该结构中的 mode 成员被设置为 flag 中的相应权限位。
* sem_otime 设置为 0。
* sem_ctime 设置为当前时间。
* sem_nsems 设置为 nsems。
参数 nsems 是该集合中的信号量数。如果是引用现有集合,可将其指定为 0。
semctl 函数的第 4 个参数是可选的,它的类型是 semun 联合体,是多个命令特定参数的联合,是否使用取决于所请求的命令。
cmd 参数指定下列 10 种命令中的一种,其中有 5 种是针对一个特定的信号量值的,它们用 semnum 指定该信号量集合中的一个成员。semnum 的值在 0 和 semget 函数的参数
nsems-1 之间。
* IPC_STAT:对此集合取 semid_ds 结构,并存储在由 arg.buf 指向的结构中。
* IPC_SET:按 arg.buf 指向的结构中的值,设置与此集合相关的结构中的 sem_perm.uid、sem_perm.gid 和 sem_perm.mode 字段。此命令只能由两种进程执行:一种是其有效用户 ID 等于 sem_perm.cuid 或 sem_perm.uid 的进程;另一种是具有超级用户特权的进程。
* IPC_RMID:从系统中立即删除该信号量集合。删除后其他进程在下次试图对此信号量集合进行操作时,将出错返回 EIDRM。该命令也只能由上面提及的两种进程执行。
* GETVAL:返回成员 semnum 的 semval 值。
* SETVAL:设置成员 semnum 的 semval 值为 arg.val 指定的值。
* GETPID:返回成员 semmum 的 sempid 值。
* GETNCNT:返回成员 semnum 的 semncnt 值。
* GETZCNT:返回成员 semnum 的 semzcnt 值。
* GETALL:取该集合中所有的信号量值,并存储在 arg.array 指向的数组中。
* SETALL:将该集合中所有的信号量值设置成 arg.array 指向的数组中的值。
对于除 GETALL 以外的所有 GET 命令,semctl 函数都返回相应值;对于其他命令,若成功则返回 0,否则返回 -1 并设置 errno。
semop 函数中的 semoparray 参数是一个由 sembuf 结构组成的信号量操作数组。nops 参数规定了该数组中操作的数量。对集合中每个成员的操作由 sembuf 结构中相应的 sem_op 值规定,它可以是负值、0 或正值,对各个情况的处理如下所述。
(1)sem_op 为正值:这对应于进程释放的占用的资源数。sem_op 值会加到信号量的值上。如果指定了 undo 标志(该标志对应于相应的 sem_flg 成员的 SEM_UNDO 位),则也从该进程的此信号量调整值中减去 sem_op。
(2)sem_op 为负值:这表示要获取由该信号量控制的资源。如若该信号量的值大于等于 sem_op 的绝对值(说明具有所需的资源),则从信号量值中减去 sem_op 的绝对值。如果指定了 undo 标志,则 sem_op 的绝对值也加到该进程的此信号量调整值上。如若信号量值小于 sem_op 的绝对值,则适用下列条件。
a)若指定了 IPC_NOWAIT,则 semop 函数出错返回 EAGAIN。
b)若未指定 IPC_NOWAIT,则该信号量的 semncnt 值加 1(因为调用进程将进入休眠),然后调用进程被挂起直至发生下列事件之一。
i. 此信号量值变成大于等于 sem_op 的绝对值(即某个进程已释放了某些资源)。此信号量的 semncnt 值减 1,并从信号量值中减去 sem_op 的绝对值。如果指定了 undo 标志,则 sem_op 的绝对值也加到该进程的此信号量调整值上。
ii. 从系统中删除了此信号量,此时 semop 函数出错返回 EIDRM。
iii. 进程捕捉到一个信号,并从信号处理程序返回。此时此信号量的 semncnt 值减 1(因为调用进程不再等待),并且 semop 函数出错返回 EINTR。
(3)sem_op 为 0:这表示调用进程希望等待到该信号量值变成 0。如果当前信号量值是 0,则 semop 函数立即返回。如果当前信号量值非 0,则适用下列条件。
a)若指定了 IPC_NOWAIT,则出错返回 EAGAIN。
b)若未指定 IPC_NOWAIT,则该信号量的 semzcnt 值加 1(因为调用进程将进入休眠),然后调用进程被挂起直至发生下列事件之一。
i. 此信号量值变成 0,此时会将此信号量的 semzcnt 值减 1。
ii. 从系统中删除了此信号量,此时 semop 函数出错返回 EIDRM。
iii. 进程捕捉到一个信号,并从信号处理程序返回。此时此信号量的 semzcnt 值减 1(因为调用进程不再等待),并且 semop 函数出错返回 EINTR。
semop 函数具有原子性,它或者执行数组中的所有操作,或者一个也不做。
前面说过,如果在进程终止时,它占用了经由信号量分配的资源,那么就会成为一个问题。无论何时只要为信号量操作指定了 SEM_UNDO 标志,然后分配资源(sem_op 值小于 0),那么内核就会记住对于该特定信号量,分配给调用进程多少资源(sem_op 的绝对值)。当该进程终止时,内核就会检验该进程是否还有尚未处理的信号量调整值,如果有,则按调整值对相应信号量进行处理。
如果用带有 SETVAL 或 SETALL 命令的 semctl 设置一个信号量的值,则在所有进程中,该信号量的调整值都将设置为 0。
发表评论
-
打开伪终端设备
2018-07-09 20:50 1265在伪终端概述一节中已对 PTY进行了初步的介绍。尽管 ... -
伪终端概述
2018-06-02 11:05 1576伪终端就是指,一个应用程序看上去像一个终端,但事实上它 ... -
终端窗口大小和 termcap
2018-05-29 22:39 812多数 UNIX 系统都提供了一种跟踪当前终端窗口大小的 ... -
终端规范模式和非规范模式
2018-05-29 00:25 977终端规范模式很简单:发一个读请求,当一行已经输入后,终 ... -
终端标识
2018-05-23 11:18 578尽管控制终端的名字在多数 UNIX 系统上都是 /de ... -
波特率和行控制函数
2018-05-22 07:53 957虽然大多数终端设 ... -
终端属性和选项标志
2018-05-20 07:40 717tcgetattr 和 tcsetattr ... -
终端特殊输入字符
2018-05-17 06:33 827终端支持下表所示的特殊输入字符。 为了更改 ... -
终端 I/O 综述
2018-05-10 07:56 452终端设备可认为是由内核中的终端驱动程序控制的。每个终端 ... -
POSIX 信号量
2018-05-09 00:03 589在XSI IPC通信之信 ... -
XSI IPC 通信之共享存储
2018-04-25 07:18 957在XSI IPC通信之消息队列和XSI IPC通信之信 ... -
XSI IPC通信之消息队列
2018-04-15 10:54 512消息队列是消息的链接表,存储在内核中,由消息队列标识符 ... -
XSI IPC 相似特征介绍
2018-02-08 23:48 492有 3 种称作 XSI IPC ... -
IPC 通信之 FIFO
2018-02-06 22:55 437FIFO 也被称为命名管道,未命名的管道只能在两个相关 ... -
IPC 通信之管道
2018-01-30 22:22 404管道是 UNIX 系统 IPC 的最古老但也是最常用的 ... -
readv/writev 函数及存储映射 I/O
2018-01-19 00:57 915readv 和 writev 函数可用于在一次函数调用 ... -
POSIX 异步 I/O
2018-01-16 21:33 470POSIX 异步 I/O 接口为对不同类型的文件进行异 ... -
fcntl 记录锁
2018-01-06 23:48 646记录锁的功能是:当有进程正在读或修改文件的某个部分时, ... -
守护进程惯例
2018-01-06 23:52 449UNIX 系统中,守护进程遵循下列通用惯例。 ... -
守护进程编写规则与出错记录
2017-12-26 01:53 464在编写守护进程程 ...
相关推荐
XSI IPC包括了三种主要机制:消息队列、信号量和共享内存。这些机制允许进程之间进行同步和通信,是多线程和多进程编程中的关键组件。 **1. 消息队列** 消息队列是一种存储消息的数据结构,进程可以将消息发送到...
其中,信号量结合共享存储区(ShareMemory)和消息传递统称为XSI IPC(扩展系统接口进程间通信),提供了一种高效的进程间通信机制。 #### 共享存储与信号量:一种高效IPC方案 文章进一步探讨了信号量与共享存储区...
本文将深入探讨"Liferay IPC(Inter-Portlet Communication)portlet间通信DEMO",并基于提供的`portlet.xml`文件来解析相关的配置信息。 1. **Liferay IPC简介** Liferay IPC机制使得不同的portlet能够共享数据和...
### XSI-ICE中文手册关键知识点解析 #### 引言:理解XSI-ICE ...尽管存在一定的功能限制,但XSI-ICE仍以其独特的灵活性和强大功能,在专业领域占据了一席之地,是值得深入研究和熟练掌握的重要工具之一。
【XSI融和球插件】是一款专为Softimage XSI(现在称为SILVERGUN)设计的强大特效工具,其在3D动画和视觉效果领域具有广泛的应用。这款插件以其独特的“融合球”技术著称,允许艺术家创建出高度复杂的形状和动态效果...
T-Gen是第一个完全整合进XSI的植物生成插件。超过100种造型和分布的参数,与XSI的...通过强大的优化工具你可以为你的游戏创造低多边形量的植物模型。几乎所有的T-Gen参数都是可动画的,因此你可以用它创建种植树木植物
XSI经典插件emFluid3破解版XSI经典插件emFluid3破解版XSI经典插件emFluid3破解版XSI经典插件emFluid3破解版
"XML中的xmlns、xmlns:xsi和xsi:schemaLocation详解" XML文档中的xmlns、xmlns:xsi和xsi:schemaLocation是三个重要的元素,分别用于定义XML文档的命名空间、XML schema实例和schemaLocation。 一、xmlns xmlns是...
字符串是 Python 中最基本的数据类型之一,用于存储文本信息。在 XSI 脚本中,字符串常用来处理文件路径、对象名称等。 **2.2.2 数字** Python 支持多种数字类型,包括整数、浮点数和复数等。这些数据类型在处理...
其中信号(signal)和信号量(semaphore)本质上并不算是进程间通信方式,应该是进程间同步的方式,但是也可以起到一定的通信作用,故也列在上面。 另外普通的mutex是作用线程间同步用的,但是可以将进程A和进程B共享的...
标题中的"SPH.rar_SPH_SPH XSI_xsi sph plugin"揭示了这是一个与流体模拟相关的软件插件,主要用于3D建模和动画软件Softimage XSI(也称为XSI)。SPH代表Smoothed Particle Hydrodynamics(平滑粒子流体动力学),这...
Autodesk SoftImage 2013 的破解工具。 你懂的
keygen downloader for xsi 2011 x 64. The way to finder keygen
XSI 7 的破解方法,图片视图,很直观,请多多支持,谢谢!!!
**Linux API速查手册概要** 本手册为Linux系统编程学习资料,全面覆盖Linux ...11. IPC对象/XSI-IPC 12. 网络编程 13. 线程 14. 基本编程 15. 线程同步 16. I/O复用 17. 异步IO(AIO) 请根据上述结构进行阅读和学习。
Softimage|XSI2012注册机 x32 x64 艺术挑战技术,技术启发艺术
第15章涵盖了多种进程间通信方式,如管道和FIFO,同时也指出了XSI IPC的局限性。第16章讲解了网络套接字编程,是网络通信的基础。第17章结合流机制和套接字讨论了高级IPC。第18章介绍了终端I/O的复杂性,第19章探讨...
UWB技术的标准制定过程中出现了Intel与TI为代表的MBOA提案和以摩托罗拉与XSI为代表的DS-CDMA提案两大阵营。虽然无线电制造商PulseLink提出了一种允许不同UWB系统共存的公共信号协议(CSP),但仍面临标准统一的问题...
### Android通过URL与Web服务器通信详解 #### 一、引言 随着移动互联网技术的发展,Android应用程序越来越多地需要与Web服务器进行数据交换。这种通信主要通过HTTP协议完成,而具体的实现方式则是通过发送请求...
15. 进程间通信:详细讨论了几种UNIX进程间通信的机制,如管道、协同进程、命名管道(FIFO)、XSIIPC(包括消息队列、共享内存和信号量)以及这些机制在C/S模型中的应用比较。 16. 网络IPC:套接字:最后一章介绍了...