int semid;
struct sembuf *sops; unsigned nsops;
说明:本系统调用用于执行用户定义的在一组信号量上操作的行为集合. 该组信号量与semid相关.
参数sops为一个用户定义的信号量操作结构数组指针. 参数nsops为该数组的元素个数. 数组的每个元素结构包括如下成员: sem_num; /* 信号量数 */ sem_op; /* 信号量操作 */ sem_flg; /* 操作标志 */
由本系统调用定义的每个信号量操作是针对由semid和sem_num指 定的信号量的.变量sem_op指定三种信号量操作的一种:
. 若sem_op为一负数并且调用进程具有修改权限,则下列情况之 一将会发生:
* 若semval不小于sem_op的绝对值,则sem_op的绝对值被减去 semval的值.若(semflg&SEM_UNDO)为真则sem_op的绝对值加 上调用进程指定的信号量的semadj值.
* 若semval小于sem_op的绝对值同时(semflg&IPC_NOWAIT)为 真,则本调用立即返回.
* 若semval小于sem_op的绝对值同时(semflg&IPC_NOWAIT)为 假,则本系统调用将增加指定信号量相关的semncnt值(加一), 将调用进程挂起直到下列条件之一被满足:
(1).semval值变成不小于sem_op的绝对值.当这种情况发 生时,指定的信号量相关的semncnt减一,若
(semflg&SEM_UNDO)为真则sem_op的绝对值加上调用 进程指定信号量的semadj值.
(2).调用进程等待的semid已被系统删除.
(3).调用进程捕俘到信号,此时,指定信号量的semncnt值 减一,调用进程执行中断服务程序.
. 若sem_op为一正值,同时调用进程具有修改权限,sem_op的值加 上semval的值,若(semflg&SEM_UNDO)为真,则sem_op减去调用 进程指定信号量的semadj值.
. 若sem_op为0,同时调用进程具有读权限,下列情况之一将会发 生:
* 若semval为0,本系统调用立即返回.
* 若semval不等于0且(semflg&IPC_NOWAIT)为真,本系统调用 立即返回.
* 若semval不等于0且(semflg&IPC_NOWAIT)为假,本系统调用 将把指定信号量的
semzcnt值加一,将调用进程挂起直到下列情况之一发生: (1).semval值变为0时,指定信号量的semzcnt值减一. (2).调用进程等待的semid已被系统删除.
(3).调用进程捕俘到信号,此时,指定信号量的semncnt值
减一,调用进程执行中断服务程序.
返回值:调用成功则返回0,否则返回-1.
例子:本例将包括上述信号量操作的所有系统调用: #include
int semid;
unsigned int count;
/*在文件sys/sem.h中定义的sembuf结构 * struct sembuf {
* unsigned short sem_num; * short sem_op; * short sem_flg;
* }*/
struct sembuf psembuf,vsembuf; /*P和V操作*/ cleanup() {
semctl(semid,2,IPC_RMID,0); exit(0); }
main(argc,argv) int argc; char *argv[]; {
int i,first,second;
short initarray[2],outarray[2]; extern cleanup(); if (argc==1) { for (i=0;i<20;i++)
signal(i,clearup);
semid=semget(SEMKEY,2,0777|IPC_CREAT); initarray[0]=initarray[1]=1;
semctl(semid,2,SETALL,initarray);
semctl(semid,2,GETALL,outarray);
printf(\ pause(); /*睡眠到被一软件中断信号唤醒*/ } else if (argv[1][0]=\ { first=0; second=1; } else { first=1; second=0;
}
semid=semget(SEMKEY,2,0777); psembuf.sem_op=-1;
psembuf.sem_flg=SEM_UNDO; vsembuf.sem_op=1;
vsembuf.sem_flg=SEM_UNDO; for (count=0;;xcount++) {
psembuf.sem_num=first; semop(semid,&psembuf,1); psembuf.sem_num=second; semop(semid,&psembuf,1);
printf(\ vsembuf.sem_num=second; semop(semid,&vsembuf,1); vsembuf.sem_num=first; semop(semid,&vsembuf,1); } }
2.24.sdenter() 共享数据段同步访问,加锁
功能:共享数据段同步访问,加锁. 语法:
#include int sdenter(addr,flags) char *addr; int flags; 说明:用于指示调用进程即将可以访问共享数据段中的内容. 参数addr为将一个sdget()调用的有效返回码. 所执行的动作取决于flags的值: . SD_NOWAIT:若另一个进程已对指定的段调用本系统调用且还没 有调用sdleave(),并且该段并非用SD_UNLOCK标志创建,则调 用进程不是等待该段空闲而是立即返回错误码. . SD_WRITE:指示调用进程希望向共享数据段写数据.此时,另一 个进程用SD_RDONLY标志联接该共享数据段则不被允许. 返回值:调用成功则返回0,否则返回-1. 2.25.sdleave() 共享数据段同步访问,解锁 功能:共享数据段同步访问,解锁. 语法: #include int sdleave(addr,flags) char *addr; 说明:用于指示调用进程已完成修改共享数据段中的内容. 返回值:调用成功则返回0,否则返回-1. 2.26.sdget() 联接共享数据段到调用进程的数据空间中 功能:联接共享数据段到调用进程的数据空间中. 语法: #include char *sdget(path,flags,size.mode) char *path; int flags; long size; int mode; 说明:本系统调用将共享数据段联接到调用进程的数据段中,具体动作 由flags的值定义: . SD_RDONLY:联接的段为只读的. . SD_WRITE:联接的段为可读写的. . SD_CREAT:若由path命名的段存在且不在使用中,本标志的作用 同早先创建一个段相同,否则,该段根据size和mode的值进程 创建.对段的读写访问权限的授予基于mode给的权限,功能与 一般文件的相同.段被初始化为全0. . SD_UNLOCK:若用此标志创建该段,则允许有多个进程同时访问 (在读写中)该段. 返回值:若调用成功则返回联接的段地址.否则返回-1. 2.27.sdfree() 将共享数据段从调用进程的数据空间中断开联接 功能:将共享数据段从调用进程的数据空间中断开联接. 语法: #include 说明:本系统调用将共享数据段从调用进程的数据段的指定地址中分离. 若调用进程已完成sdenter()的调用,还未调用sdleave()就调用 本系统调用,则sdleave()被自动调用,然后才做本调用的工作. 返回值:若调用成功则返回联接的段地址.否则返回-1. 2.28.sdgetv() 同步共享数据访问 功能:同步共享数据访问. 语法: #include 说明:用于同步协调正在使用共享数据段的进程.返回值为共享数据段 的版本号.当有进程对该段做sdleave()操作时,版本号会被修改. 返回值:若调用成功,则返回指定共享数据段的版本号,否则返回-1. 2.29.sdwaitv() 同步共享数据访问 功能:同步共享数据访问. 语法: #include 说明:用于同步协调正在使用共享数据段的进程.返回值为共享数据段 的版本号.调用进程会睡眠直到指定段的版本号不再等于vnum; 返回值:若调用成功,则返回指定共享数据段的版本号,否则返回-1. 2.30.sbrk() 修改数据段空间分配 功能:修改数据段空间分配. 语法: char *sbrk(incr) int incr; 说明:用于动态修改调用进程数据段的空间分配.进程将重置进程的分 段值并分配一个合适大小的空间.分段值为数据段外第一次分配 的地址.要分配的空间的增加量等于分段值的增加量.新分配的空 间设置为0.若相同的内存空间重新分配给同一个进程,则空间的 内容不确定. 返回值:若成功调用则返回值为0,否则返回-1. 例子:本例将包括上述共享数据空间操作的所有系统调用: char * area1; char buf[21]; int v; /*取得或创建一个共享数据空间(系统特殊文件),名字为 /tmp/area1,长度为640,用户访问权限为0777*/ area1=sdget(\T,640,0777);