• 共享内存及信号量的几个函数介绍


    1.msgrcv()
            功能:从消息队列中取得指定类型的消息.
            语法:#include <sys/types.h>
                 #include <sys/ipc.h>
                 #include <sys/msg.h>
                 int msgrcv(msqid,msgp,msgsz,msgtyp,msgflg)
                 int msqid;
                 void *msgp;
                 int msgsz;
                 long msgtyp;
                 int msgflg;
            说明:本系统调用从由msqid指定的消息队列中读取一个由msgtyp指定
                 类型的消息到由msgp指向的缓冲区中,同样的,该缓冲区的结构如

                 前所述,包括消息类型和消息正文.msgsz为可接收的消息正文的
                 字节数.若接收到的消息正文的长度大于msgsz,则会被截短到
                 msgsz字节为止(当消息标志msgflg&MSG_NOERROR为真时),截掉的

                 部份将被丢失,而且不通知消息发送进程.
                 msgtyp指定消息类型:
                 . 为0则接收消息队列中第一个消息.
                 . 大于0则接收消息队列中第一个类型为msgtyp的消息.
                 . 小于0则接收消息队列中第一个类型值不小于msgtyp绝对值且
                   类型值又最小的消息.
                 msgflg指定操作行为:
                 . 若(msgflg&IPC_NOWAIT)是真的,调用进程会立即返回,若没有
                   接收到消息则返回值为-1,errno设置为ENOMSG.
                 . 若(msgflg&IPC_NOWAIT)不是真的,则调用进程会被挂起直到下

                   面情况之一发生:
                     * 队列中的消息的类型是有效的.
                     * 消息队列标志被系统删除.系统调用返回-1.
                     * 调用进程接收到一个未被忽略的中断信号,调用进程继续
                       执行或被终止.
                 调用成功后,对应指定的消息队列的相关结构做如下动作:
                 . 消息数(msg_qnum)减1.
                 . 消息队列最近接收进程号(msg_lrpid)改为调用进程号.
                 . 消息队列接收时间(msg_rtime)改为当前系统时间.
                 以上信息可用命令ipcs -a看到.
            返回值:调用成功则返回值等于接收到实际消息正文的字节数.
                 不成功则返回-1. 

    2.msgctl()
            功能:消息控制操作
            语法:#include <sys/types.h>
                 #include <sys/ipc.h>
                 #include <sys/msg.h>
                 int msgctl(msqid,cmd,buf)
                 int msqid,cmd;
                 struct msqid_ds *buf;
            说明:本系统调用提供一系列消息控制操作,操作动作由cmd定义,以下
                 cmd定义值表明了各操作动作的定义.
                 . IPC_STAT:将msqid相关的数据结构中各个元素的当前值放入由

                     buf指向的结构中.
                 . IPC_SET:将msqid相关的数据结构中的下列元素设置为由buf指

                     向的结构中的对应值.
                     msg_perm.uid
                     msg_perm.gid
                     msg_perm.mode
                     msg_qbytes
                     本命令只能由有效UID等于msg_perm.cuid或msg_perm.uid的

                     进程或有效UID有合适权限的进程操作.只有具有合适权限的

                     用户才能增加msg_qbytes的值.
                 . IPC_RMID:删除由msqid指示的消息队列.将它从系统中删除并
                     破坏相关的数据结构.
                     本命令只能由有效UID等于msg_perm.cuid或msg_perm.uid的

                     进程或有效UID有合适权限的进程操作.
            返回值:调用成功则返回值为0,否则为-1. 
    3.msgget()
            功能:取得一个消息队列.
            语法:#include <sys/types.h>
                 #include <sys/ipc.h>
                 #include <sys/msg.h>
                 int msgget(key,msgflg)
                 key_t key;
                 int msgflg;
            说明:本系统调用返回与参数key相关的消息队列的标识符.
                 若以下事实成立,则与消息队列相关的标识符和数据结构将被创
                 建出来:
                 . 若参数key等于IPC_PRIVATE.
                 . 若参数key没有一个已存在的消息队列标识符与之相关,同时值

                   (msgflg&IPC_CREAT)为真.
                 创建消息队列时,与新的消息队列标识符相关的数据结构将被初
                 始化为如下:
                 . msg_perm.cuid和msg_perm.uid设置为调用进程的有效UID.
                 . msg_perm.cgid和msg_perm.gid设置为调用进程的有效GID.
                 . msg_perm.mode访问权限比特位设置为msgflg访问权限比特位.

                 . msg_qnum,msg_lspid,msg_lrpid,msg_stime,msg_rtime设置为0
    .
                 . msg_ctime设置为当前系统时间.
                 . msg_qbytes设置为系统允许的最大值.
            返回值:调用成功则返回一非0值,称为消息队列标识符;否则返回值为-1
    .
            例子:本例将包括上述所有消息队列操作的系统调用:
                 #define RKEY 0x9001L    /*读消息队列的KEY值*/
                 #define WKEY 0x9002L    /*写消息队列的KEY值*/
                 #define MSGFLG 0666     /*消息队列访问权限*/
                 #define IPC_WAIT 0      /*等待方式在include文件中未定义*/

                 int rmsqid;             /*读消息队列标识符*/
                 int wmsqid;             /*写消息队列标识符*/
                 struct msgbuf {
                     long mtype;
                     char mtext[200];
                 } buf;
                 /*若读消息队列已存在就取得标识符,否则则创建并取得标识符*/

                 if ((rmsqid=msgget(RKEY,MSGFLG|IPC_CREAT))<0) {
    printf("get read message queue failed ");
    exit(1);
    }
    /*若写消息队列已存在则失败,若不存在则创建并取得标识符*/
    if ((wmsqid=msgget(WKEY,
    MSGFLG|IPC_CREAT|IPC_TRUNC))<0) {
    printf("get write message queue failed ");
    exit(2);
    }
    /*接收所有类型的消息*/
    if (msgrcv(rmsqid,&buf,sizeof(struct msgbuf)-sizeof(long)
    ,
    0L,IPC_WAIT)>0)                  printf("get %ld type message from queue:%s ",
                            buf.mtype,buf.mtext);
                 else {
                     printf("get message failed ");
                     exit(3);
                 }
                 buf.mtype=3L
                 if (msgsnd(wmsqid,&buf,sizeof(struct msgbuf)-sizeof(long)
    ,
                      IPC_NOWAIT)>0)
                     printf("send message OK ");
                 else {
                     printf("send message failed ");
                     exit(4);
                 }
                 msgctl(wmsqid,IPC_RMID,(struct msqid *)NULL);

    4.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. 

    5.shmdt()
            功能:断开共享内存联接的操作.
            语法:#include <sys/types.h>
                 #include <sys/ipc.h>
                 #include <sys/shm.h>
                 void *shmdt(shmaddr)
                 void *shmaddr;
            说明:本系统调用将由shmaddr指定的共享内存段从调用进程的数据段
                 脱离出去.
            返回值:若调用成功则返回值为0,否则返回值为-1. 
    6.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.

    7.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 ",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 value%d ",i,*pint++);
    shmdt(addr1);
    shmdt(addr2);
    pause();
    }
    8.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. 
    9.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.

    10.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 ",
    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 ",getpid(),count);
    vsembuf.sem_num=second;
    semop(semid,&vsembuf,1);
    vsembuf.sem_num=first;
    semop(semid,&vsembuf,1);
    }
    }

  • 相关阅读:
    荣誉追记
    通过代码实现 Windows Mobile 窗体的最小化 (转)
    软件协会周年庆(高清晰)
    菜鸟级注册与限制
    Ajax Tree (转)
    转职场别做愤青
    菜鸟级分页用户控件
    Windows Mobile 常用键值(VK)对应表及系统文件夹简单介绍
    12.Linux软件包管理相关操作
    5.Docker应用
  • 原文地址:https://www.cnblogs.com/honglihua8688/p/3686123.html
Copyright © 2020-2023  润新知