22.semget()
功能:取得一组信号量.
语法:#include
#include
#include
int semget(key,nsems,semflg)
key_t key;
int nsems,semflg;
说明:返回和key相关的信号量标识符.
若以下事实成立,则与信号量标识符,与之相关的semid_ds数据结
构及一组nsems信号量将被创建:
. key等于IPC_PRIVATE.
. 系统内还没有与key相关的信号量,同时(semflg&IPC_CREAT)
为真.
创建时新的信号量相关的semid_ds数据结构被初始化如下:
. 在操作权限结构,sem_perm.cuid和sem_perm.uid设置等于调用
进程的有效UID.
. 在操作权限结构,sem_perm.cgid和sem_perm.gid设置等于调用
进程的有效GID.
. 访问权限比特位sem_perm.mode设置等于semflg的访问权限比
特位.
. sem_otime设置等于0,sem_ctime设置等于当前系统时间.
返回值:若调用成功,则返回一非0值,称为信号量标识符;否则返回-1.
23.semop()
功能:信号量操作.
语法:#include
#include
#include
int semop(semid,sops,nsops)
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
#include
#include
#define SEMKEY 75
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("sem init vals %d%d \n",
outarray[0],outarray[1]);
pause(); /*睡眠到被一软件中断信号唤醒*/
}
else if (argv[1][0]=='a') {
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("proc %d count %d\n",getpid(),count);
vsembuf.sem_num=second;
semop(semid,&vsembuf,1);
vsembuf.sem_num=first;
semop(semid,&vsembuf,1);
}
}
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.
25.sdleave()
功能:共享数据段同步访问,解锁.
语法:#include
int sdleave(addr,flags)
char *addr;
说明:用于指示调用进程已完成修改共享数据段中的内容.
返回值:调用成功则返回0,否则返回-1.
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.
阅读(870) | 评论(0) | 转发(0) |