|

楼主 |
发表于 2003-6-3 21:32:51
|
显示全部楼层
- 17.shmat()
- 功能:联接共享内存的操作.
- 语法:#include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/shm.h>
- void *shmat(shmid,shmaddr,shmflg)
- int shmid;
- void *shmaddr;
- int shmid;
- 说明:将由shmid指示的共享内存联接到调用进程的数据段中.被联接的
- 段放在地址,该地址由以下准则指定:
- . 若shmaddr等于(void *)0,则段联接到由系统选择的第一个可
- 用的地址上.
- . 若shmaddr不等于(void *)0同时(shmflg&SHM_RND)值为真,则
- 段联接到由(shmaddr-(shmaddr%SHMLBA))给出的地址上.
- . 若shmaddr不等于(void *)0同时(shmflg&SHM_RND)值为假,则
- 段联接到由shmaddr指定的地址上.
- 若(shmflg&sSHM_RDONLY)为真并且调用进程有读允许,则被联接
- 的段为只读;否则,若值不为真且调用进程有读写权限,则被联接
- 的段为可读写的.
- 返回值:若调用成功则返回被联接的共享内存段在数据段上的启始地址.
- 否则返回值为-1.
- 18.shmdt()
- 功能:断开共享内存联接的操作.
- 语法:#include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/shm.h>
- void *shmdt(shmaddr)
- void *shmaddr;
- 说明:本系统调用将由shmaddr指定的共享内存段从调用进程的数据段
- 脱离出去.
- 返回值:若调用成功则返回值为0,否则返回值为-1.
- 19.shmget()
- 功能:取得共享内存段
- 语法:#include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/shm.h>
- int shmget(key,size,shmflg)
- key_t key;
- int size,shmflg;
- 说明:本系统调用返回key相关的共享内存标识符.
- 共享内存标识符和相关数据结构及至少size字节的共享内存段能
- 正常创建,要求以下事实成立:
- . 参数key等于IPC_PRIVATE.
- . 参数key没有相关的共享内存标识符,同时(shmflg&IPC_CREAT)
- 值为真.
- 共享内存创建时,新生成的共享内存标识相关的数据结构被初始
- 化如下:
- . shm_perm.cuid和shm_perm.uid设置为调用进程的有效UID.
- . shm_perm.cgid和shm_perm.gid设置为调用进程的有效GID.
- . shm_perm.mode访问权限比特位设置为shmflg访问权限比特位.
- . shm_lpid,shm_nattch,shm_atime,shm_dtime设置为0.
- . shm_ctime设置为当前系统时间.
- . shm_segsz设置为0.
- 返回值:若调用成功则返回一个非0值,称为共享内存标识符,否则返回
- 值为-1.
- 20.shmctl()
- 功能:共享内存控制操作.
- 语法:#include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/shm.h>
- int shmctl(shmid,cmd,buf)
- int shmid,cmd;
- struct shmid_ds *buf;
- 说明:本系统调用提供一系列共享内存控制操作.操作行为由cmd指定.
- 以下为cmd的有效值:
- . IPC_STAT:将shmid相关的数据结构中各个元素的当前值放入由
- buf指向的结构中.
- . IPC_SET:将shmid相关的数据结构中的下列元素设置为由buf指
- 向的结构中的对应值.
- shm_perm.uid
- shm_perm.gid
- shm_perm.mode
- 本命令只能由有效UID等于shm_perm.cuid或shm_perm.uid的
- 进程或有效UID有合适权限的进程操作.
- . IPC_RMID:删除由shmid指示的共享内存.将它从系统中删除并
- 破坏相关的数据结构.
- 本命令只能由有效UID等于shm_perm.cuid或shm_perm.uid的
- 进程或有效UID有合适权限的进程操作.
- 返回值:若调用成功则返回0,否则返回-1.
-
- 例子:本例包括上述所有共享内存操作系统调用:
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/shm.h>
- #define SHMKEY 74
- #define K 1024
- int shmid;
- cleanup()
- {
- shmctl(shmid,IPC_RMID,0);
- exit(0);
- }
- main()
- {
- int *pint;
- char *addr1,*addr2;
- extern char *shmat();
- extern cleanup();
- for (i=0;i<20;i++)
- signal(i,cleanup);
- shmid=shmget(SHMKEY,128*K,0777|IPC_CREAT);
- addr1=shmat(shmid,0,0);
- addr2=shmat(shmid,0,0);
- printf("addr1 0x%x addr2 0x%x\n",addr1,addr2);
- pint=(int*)addr1;
- for (i=0;i<256;i++)
- *pint++=i;
- pint=(int*)addr1;
- *pint=256;
- pint=(int*)addr2;
- for (i=0;i<256;i++)
- printf("index %d\tvalue%d\n",i,*pint++);
- shmdt(addr1);
- shmdt(addr2);
- pause();
- }
-
- 21.semctl()
- 功能:信号量控制操作.
- 语法:#include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- int semctl(semid,memnum,cmd,arg)
- int semid,semnum,cmd;
- union semun {
- int val;
- struct semid_ds *buf;
- ushort *array;
- }arg;
- 说明:本系统调用提供了一个信号量控制操作,操作行为由cmd定义,这
- 些命令是对由semid和semnum指定的信号量做操作的.每个命令都
- 要求有相应的权限级别:
- . GETVAL:返回semval的值,要求有读权限.
- . SETVAL:设置semval的值到arg.val上.此命令成功执行后,
- semadj的值对应的所有进程的信号量全部被清除,要求有修
- 改权限.
- . GETPID:返回sempid的值,要求有读权限.
- . GETNCNT:返回semncnt的值,要求有读权限.
- . GETZCNT:返回semzcnt的值,要求有读权限.
- 以下命令在一组信号量中的各个semval上操作:
- . GETALL:返回每个semval的值,同时将各个值放入由arg.array
- 指向的数组中.当此命令成功执行后,semadj的值对应的所有
- 进程的信号量全部被清除,要求有修改权限.
- . SETALL:根据由arg.array指向的数组设置各个semval值.当此
- 命令成功执行后,semadj的值对应的所有进程的信号量全部
- 被清除,要求有修改权限.
- 以下命令在任何情况下都是有效的:
- . IPC_STAT:将与semid相关的数据结构的各个成员的值放入由
- arg.buf指向的结构中.要求有读权限.
- . IPC_SET:设置semid相关数据结构的如下成员,设置数据从
- arg.buf指向的结构中读取:
- sem_perm.uid
- sem_perm.gid
- sem_perm.mode
- 本命令只能由有效UID等于sem_perm.cuid或sem_perm.uid的
- 进程或有效UID有合适权限的进程操作.
- . IPC_RMID:删除由semid指定的信号量标识符和相关的一组信号
- 量及数据结构.本命令只能由有效UID等于sem_perm.cuid或
- sem_perm.uid的进程或有效UID有合适权限的进程操作.
- 返回值:若调用成功,则根据cmd返回以下值:
- GETVAL:semval的值.
- GETPID:sempid的值.
- GETNCNT:semncnt的值.
- GETZCNT:semzcnt的值.
- 其他:0.
- 若调用失败则返回-1.
- 22.semget()
- 功能:取得一组信号量.
- 语法:#include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- 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 <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- 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 <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- #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 <sys/sd.h>
- 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 <sys/sd.h>
- int sdleave(addr,flags)
- char *addr;
- 说明:用于指示调用进程已完成修改共享数据段中的内容.
- 返回值:调用成功则返回0,否则返回-1.
- 26.sdget()
- 功能:联接共享数据段到调用进程的数据空间中.
- 语法:#include <sys/sd.h>
- 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.
- 27.sdfree()
- 功能:将共享数据段从调用进程的数据空间中断开联接.
- 语法:#include <sys/sd.h>
- int sdfree(addr)
- char *addr;
- 说明:本系统调用将共享数据段从调用进程的数据段的指定地址中分离.
- 若调用进程已完成sdenter()的调用,还未调用sdleave()就调用
- 本系统调用,则sdleave()被自动调用,然后才做本调用的工作.
- 返回值:若调用成功则返回联接的段地址.否则返回-1.
- 28.sdgetv()
- 功能:同步共享数据访问.
- 语法:#include <sys/sd.h>
- int sdgetv(addr)
- char *addr;
- 说明:用于同步协调正在使用共享数据段的进程.返回值为共享数据段
- 的版本号.当有进程对该段做sdleave()操作时,版本号会被修改.
- 返回值:若调用成功,则返回指定共享数据段的版本号,否则返回-1.
- 29.sdwaitv()
- 功能:同步共享数据访问.
- 语法:#include <sys/sd.h>
- int sdwaitv(addr,vnum)
- char *addr;
- int vnum;
- 说明:用于同步协调正在使用共享数据段的进程.返回值为共享数据段
- 的版本号.调用进程会睡眠直到指定段的版本号不再等于vnum;
- 返回值:若调用成功,则返回指定共享数据段的版本号,否则返回-1.
- 30.sbrk()
- 功能:修改数据段空间分配.
- 语法:char *sbrk(incr)
- int incr;
- 说明:用于动态修改调用进程数据段的空间分配.进程将重置进程的分
- 段值并分配一个合适大小的空间.分段值为数据段外第一次分配
- 的地址.要分配的空间的增加量等于分段值的增加量.新分配的空
- 间设置为0.若相同的内存空间重新分配给同一个进程,则空间的
- 内容不确定.
- 返回值:若成功调用则返回值为0,否则返回-1.
-
- 例子:本例将包括上述共享数据空间操作的所有系统调用:
- char * area1;
- char buf[21];
- int v;
- /*取得或创建一个共享数据空间(系统特殊文件),名字为
- /tmp/area1,长度为640,用户访问权限为0777*/
- area1=sdget("/tmp/area1",SD_WRITE|SD_CREAT,640,0777);
- if ((int)area1==-1) {
- printf("get share data segment area1 failed\n");
- exit(1);
- }
- /*取得共享数据段area1的版本号*/
- v=sdgetv(area1);
- /*申请访问共享数据段area1,若已有进程在访问该段则本进程挂
- *起,否则进入访问并将该数据段加写锁*/
- sdenter(area1,SD_WRITE);
- /*对共享数据段访问,写10个a*/
- strcpy(area1,"aaaaaaaaaa");
- /*申请解除访问权限,若已有进程申请访问则激活该进程*/
- sdleave(area1);
- /*进程处理过程*/
- /*等待取共享数据段area1的版本号*/
- sdwaitv(area1,v);
- /*重新申请访问共享数据段area1*/
- sdenter(area1,SD_WRITE);
- /*读取共享数据段中的数据*/
- memcpy(buf,area1,20);
- /*申请解除访问权限,若已有进程申请访问则激活该进程*/
- sdleave(area1);
- printf("the data now in area1 is [%s]\n",buf);
-
复制代码 |
|