📄 program-multi-fork.html
字号:
<br>段联接到由shmaddr指定的地址上.
<br>若(shmflg&sSHM_RDONLY)为真并且调用进程有读允许,则被联接
<br>的段为只读;否则,若值不为真且调用进程有读写权限,则被联接
<br>的段为可读写的.
<br>返回值:若调用成功则返回被联接的共享内存段在数据段上的启始地址.
<br>否则返回值为-1.
<br>18.shmdt()
<br>功能:断开共享内存联接的操作.
<br>语法:#include
<br>#include
<br>#include
<br>void *shmdt(shmaddr)
<br>void *shmaddr;
<br>说明:本系统调用将由shmaddr指定的共享内存段从调用进程的数据段
<br>脱离出去.
<br>返回值:若调用成功则返回值为0,否则返回值为-1.
<br>19.shmget()
<br>功能:取得共享内存段
<br>语法:#include
<br>#include
<br>#include
<br>int shmget(key,size,shmflg)
<br>key_t key;
<br>int size,shmflg;
<br>说明:本系统调用返回key相关的共享内存标识符.
<br>共享内存标识符和相关数据结构及至少size字节的共享内存段能
<br>正常创建,要求以下事实成立:
<br>. 参数key等于IPC_PRIVATE.
<br>. 参数key没有相关的共享内存标识符,同时(shmflg&IPC_CREAT)
<br>值为真.
<br>共享内存创建时,新生成的共享内存标识相关的数据结构被初始
<br>化如下:
<br>. shm_perm.cuid和shm_perm.uid设置为调用进程的有效UID.
<br>. shm_perm.cgid和shm_perm.gid设置为调用进程的有效GID.
<br>. shm_perm.mode访问权限比特位设置为shmflg访问权限比特位.
<br>. shm_lpid,shm_nattch,shm_atime,shm_dtime设置为0.
<br>. shm_ctime设置为当前系统时间.
<br>. shm_segsz设置为0.
<br>返回值:若调用成功则返回一个非0值,称为共享内存标识符,否则返回
<br>值为-1.
<br>20.shmctl()
<br>功能:共享内存控制操作.
<br>语法:#include
<br>#include
<br>#include
<br>int shmctl(shmid,cmd,buf)
<br>int shmid,cmd;
<br>struct shmid_ds *buf;
<br>说明:本系统调用提供一系列共享内存控制操作.操作行为由cmd指定.
<br>以下为cmd的有效值:
<br>. IPC_STAT:将shmid相关的数据结构中各个元素的当前值放入由
<br>buf指向的结构中.
<br>. IPC_SET:将shmid相关的数据结构中的下列元素设置为由buf指
<br>向的结构中的对应值.
<br>shm_perm.uid
<br>shm_perm.gid
<br>shm_perm.mode
<br>本命令只能由有效UID等于shm_perm.cuid或shm_perm.uid的
<br>进程或有效UID有合适权限的进程操作.
<br>. IPC_RMID:删除由shmid指示的共享内存.将它从系统中删除并
<br>破坏相关的数据结构.
<br>本命令只能由有效UID等于shm_perm.cuid或shm_perm.uid的
<br>进程或有效UID有合适权限的进程操作.
<br>返回值:若调用成功则返回0,否则返回-1.
<br>例子:本例包括上述所有共享内存操作系统调用:
<br>#include
<br>#include
<br>#include
<br>#define SHMKEY 74
<br>#define K 1024
<br>int shmid;
<br>cleanup()
<br>{
<br>shmctl(shmid,IPC_RMID,0);
<br>exit(0);
<br>}
<br>main()
<br>{
<br>int *pint;
<br>char *addr1,*addr2;
<br>extern char *shmat();
<br>extern cleanup();
<br>for (i=0;i<20;i++)
<br>signal(i,cleanup);
<br>shmid=shmget(SHMKEY,128*K,0777|IPC_CREAT);
<br>addr1=shmat(shmid,0,0);
<br>addr2=shmat(shmid,0,0);
<br>printf("addr1 0x%x addr2 0x%x\n",addr1,addr2);
<br>pint=(int*)addr1;
<br>for (i=0;i<256;i++)
<br>*pint++=i;
<br>pint=(int*)addr1;
<br>*pint=256;
<br>pint=(int*)addr2;
<br>for (i=0;i<256;i++)
<br>printf("index %d\tvalue%d\n",i,*pint++);
<br>shmdt(addr1);
<br>shmdt(addr2);
<br>pause();
<br>}
<br>21.semctl()
<br>功能:信号量控制操作.
<br>语法:#include
<br>#include
<br>#include
<br>int semctl(semid,memnum,cmd,arg)
<br>int semid,semnum,cmd;
<br>union semun {
<br>int val;
<br>struct semid_ds *buf;
<br>ushort *array;
<br>}arg;
<br>说明:本系统调用提供了一个信号量控制操作,操作行为由cmd定义,这
<br>些命令是对由semid和semnum指定的信号量做操作的.每个命令都
<br>要求有相应的权限级别:
<br>. GETVAL:返回semval的值,要求有读权限.
<br>. SETVAL:设置semval的值到arg.val上.此命令成功执行后,
<br>semadj的值对应的所有进程的信号量全部被清除,要求有修
<br>改权限.
<br>. GETPID:返回sempid的值,要求有读权限.
<br>. GETNCNT:返回semncnt的值,要求有读权限.
<br>. GETZCNT:返回semzcnt的值,要求有读权限.
<br>以下命令在一组信号量中的各个semval上操作:
<br>. GETALL:返回每个semval的值,同时将各个值放入由arg.array
<br>指向的数组中.当此命令成功执行后,semadj的值对应的所有
<br>进程的信号量全部被清除,要求有修改权限.
<br>. SETALL:根据由arg.array指向的数组设置各个semval值.当此
<br>命令成功执行后,semadj的值对应的所有进程的信号量全部
<br>被清除,要求有修改权限.
<br>以下命令在任何情况下都是有效的:
<br>. IPC_STAT:将与semid相关的数据结构的各个成员的值放入由
<br>arg.buf指向的结构中.要求有读权限.
<br>. IPC_SET:设置semid相关数据结构的如下成员,设置数据从
<br>arg.buf指向的结构中读取:
<br>sem_perm.uid
<br>sem_perm.gid
<br>sem_perm.mode
<br>本命令只能由有效UID等于sem_perm.cuid或sem_perm.uid的
<br>进程或有效UID有合适权限的进程操作.
<br>. IPC_RMID:删除由semid指定的信号量标识符和相关的一组信号
<br>量及数据结构.本命令只能由有效UID等于sem_perm.cuid或
<br>sem_perm.uid的进程或有效UID有合适权限的进程操作.
<br>返回值:若调用成功,则根据cmd返回以下值:
<br>GETVAL:semval的值.
<br>GETPID:sempid的值.
<br>GETNCNT:semncnt的值.
<br>GETZCNT:semzcnt的值.
<br>其他:0.
<br>若调用失败则返回-1.
<br>22.semget()
<br>功能:取得一组信号量.
<br>语法:#include
<br>#include
<br>#include
<br>int semget(key,nsems,semflg)
<br>key_t key;
<br>int nsems,semflg;
<br>说明:返回和key相关的信号量标识符.
<br>若以下事实成立,则与信号量标识符,与之相关的semid_ds数据结
<br>构及一组nsems信号量将被创建:
<br>. key等于IPC_PRIVATE.
<br>. 系统内还没有与key相关的信号量,同时(semflg&IPC_CREAT)
<br>为真.
<br>创建时新的信号量相关的semid_ds数据结构被初始化如下:
<br>. 在操作权限结构,sem_perm.cuid和sem_perm.uid设置等于调用
<br>进程的有效UID.
<br>. 在操作权限结构,sem_perm.cgid和sem_perm.gid设置等于调用
<br>进程的有效GID.
<br>. 访问权限比特位sem_perm.mode设置等于semflg的访问权限比
<br>特位.
<br>. sem_otime设置等于0,sem_ctime设置等于当前系统时间.
<br>返回值:若调用成功,则返回一非0值,称为信号量标识符;否则返回-1.
<br>23.semop()
<br>功能:信号量操作.
<br>语法:#include
<br>#include
<br>#include
<br>int semop(semid,sops,nsops)
<br>int semid;
<br>struct sembuf *sops;
<br>unsigned nsops;
<br>说明:本系统调用用于执行用户定义的在一组信号量上操作的行为集合.
<br>该组信号量与semid相关.
<br>参数sops为一个用户定义的信号量操作结构数组指针.
<br>参数nsops为该数组的元素个数.
<br>数组的每个元素结构包括如下成员:
<br>sem_num; /* 信号量数 */
<br>sem_op; /* 信号量操作 */
<br>sem_flg; /* 操作标志 */
<br>由本系统调用定义的每个信号量操作是针对由semid和sem_num指
<br>定的信号量的.变量sem_op指定三种信号量操作的一种:
<br>. 若sem_op为一负数并且调用进程具有修改权限,则下列情况之
<br>一将会发生:
<br>* 若semval不小于sem_op的绝对值,则sem_op的绝对值被减去
<br>semval的值.若(semflg&SEM_UNDO)为真则sem_op的绝对值加
<br>上调用进程指定的信号量的semadj值.
<br>* 若semval小于sem_op的绝对值同时(semflg&IPC_NOWAIT)为
<br>真,则本调用立即返回.
<br>* 若semval小于sem_op的绝对值同时(semflg&IPC_NOWAIT)为
<br>假,则本系统调用将增加指定信号量相关的semncnt值(加一),
<br>将调用进程挂起直到下列条件之一被满足:
<br>(1).semval值变成不小于sem_op的绝对值.当这种情况发
<br>生时,指定的信号量相关的semncnt减一,若
<br>(semflg&SEM_UNDO)为真则sem_op的绝对值加上调用
<br>进程指定信号量的semadj值.
<br>(2).调用进程等待的semid已被系统删除.
<br>(3).调用进程捕俘到信号,此时,指定信号量的semncnt值
<br>减一,调用进程执行中断服务程序.
<br>. 若sem_op为一正值,同时调用进程具有修改权限,sem_op的值加
<br>上semval的值,若(semflg&SEM_UNDO)为真,则sem_op减去调用
<br>进程指定信号量的semadj值.
<br>. 若sem_op为0,同时调用进程具有读权限,下列情况之一将会发
<br>生:
<br>* 若semval为0,本系统调用立即返回.
<br>* 若semval不等于0且(semflg&IPC_NOWAIT)为真,本系统调用
<br>立即返回.
<br>* 若semval不等于0且(semflg&IPC_NOWAIT)为假,本系统调用
<br>将把指定信号量的
<br>semzcnt值加一,将调用进程挂起直到下列情况之一发生:
<br>(1).semval值变为0时,指定信号量的semzcnt值减一.
<br>(2).调用进程等待的semid已被系统删除.
<br>(3).调用进程捕俘到信号,此时,指定信号量的semncnt值
<br>减一,调用进程执行中断服务程序.
<br>返回值:调用成功则返回0,否则返回-1.
<br>例子:本例将包括上述信号量操作的所有系统调用:
<br>#include
<br>#include
<br>#include
<br>#define SEMKEY 75
<br>int semid;
<br>unsigned int count;
<br>/*在文件sys/sem.h中定义的sembuf结构
<br>* struct sembuf {
<br>* unsigned short sem_num;
<br>* short sem_op;
<br>* short sem_flg;
<br>* }*/
<br>struct sembuf psembuf,vsembuf; /*P和V操作*/
<br>cleanup()
<br>{
<br>semctl(semid,2,IPC_RMID,0);
<br>exit(0);
<br>}
<br>main(argc,argv)
<br>int argc;
<br>char *argv[];
<br>{
<br>int i,first,second;
<br>short initarray[2],outarray[2];
<br>extern cleanup();
<br>if (argc==1) {
<br>for (i=0;i<20;i++)
<br>signal(i,clearup);
<br>semid=semget(SEMKEY,2,0777|IPC_CREAT);
<br>initarray[0]=initarray[1]=1;
<br>semctl(semid,2,SETALL,initarray);
<br>semctl(semid,2,GETALL,outarray);
<br>printf("sem init vals %d%d \n",
<br>outarray[0],outarray[1]);
<br>pause(); /*睡眠到被一软件中断信号唤醒*/
<br>}
<br>else if (argv[1][0]=='a') {
<br>first=0;
<br>second=1;
<br>}
<br>else {
<br>first=1;
<br>second=0;
<br>}
<br>semid=semget(SEMKEY,2,0777);
<br>psembuf.sem_op=-1;
<br>psembuf.sem_flg=SEM_UNDO;
<br>vsembuf.sem_op=1;
<br>vsembuf.sem_flg=SEM_UNDO;
<br>for (count=0;;xcount++) {
<br>psembuf.sem_num=first;
<br>semop(semid,&psembuf,1);
<br>psembuf.sem_num=second;
<br>semop(semid,&psembuf,1);
<br>printf("proc %d count %d\n",getpid(),count);
<br>vsembuf.sem_num=second;
<br>semop(semid,&vsembuf,1);
<br>vsembuf.sem_num=first;
<br>semop(semid,&vsembuf,1);
<br>}
<br>}
<br>24.sdenter()
<br>功能:共享数据段同步访问,加锁.
<br>语法:#include
<br>int sdenter(addr,flags)
<br>char *addr;
<br>int flags;
<br>说明:用于指示调用进程即将可以访问共享数据段中的内容.
<br>参数addr为将一个sdget()调用的有效返回码.
<br>所执行的动作取决于flags的值:
<br>. SD_NOWAIT:若另一个进程已对指定的段调用本系统调用且还没
<br>有调用sdleave(),并且该段并非用SD_UNLOCK标志创建,则调
<br>用进程不是等待该段空闲而是立即返回错误码.
<br>. SD_WRITE:指示调用进程希望向共享数据段写数据.此时,另一
<br>个进程用SD_RDONLY标志联接该共享数据段则不被允许.
<br>返回值:调用成功则返回0,否则返回-1.
<br>25.sdleave()
<br>功能:共享数据段同步访问,解锁.
<br>语法:#include
<br>int sdleave(addr,flags)
<br>char *addr;
<br>说明:用于指示调用进程已完成修改共享数据段中的内容.
<br>返回值:调用成功则返回0,否则返回-1.
<br>26.sdget()
<br>功能:联接共享数据段到调用进程的数据空间中.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -