打印

System V 的 IPC -- 线程通信机制

[复制链接]
403|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
社畜一枚|  楼主 | 2018-8-22 09:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
一、IPC (Inter-Process Communication):  --中文翻译是线程间的通信消息队列共享内存(效率最高)信号灯集







二、客户端命令:ipcs:--用来查看system V的IPC机制标识符的命令

       -q,显示当前系统中  消息队列  的使用

        -m,显示当前系统中 共享内存  的使用

        -s,  显示当前系统中 信号量     的使用



ipcrm:--用来删除 当前系统中 system V的IPC机制标识符的命令

        -q,删除当前系统中 消息队列的标识符



        -m,删除当前系统中 共享内存的标识符

        -s,删除当前系统中 信号灯集的标识符

比如:

    ipcrm -m 共享内存的id



三、具体:

消息队列:--消息队列可以看做是若干个FIFO的集合,每个FIFO存放不同类型的消息。1. msgget    消息队列的创建、打开

2. msgsnd    往消息队列中写消息

3. msgrcv    读取消息或接收一条消息

4. msgctl     控制函数(获取、设置、删除)



1. msgget:消息队列的创建、打开包含的库:

     #include <sys/types.h>

     #include <sys/ipc.h>

     #include <sys/msg.h>

函数原型:

    int msgget(key_t key, int msg**);

参数:

    ①key,ftok获得的值

    ②msg**,

        IPC_CREAT,创建

        IPC_EXCL   ,有错误,就提醒

返回值:

    消息队列的标识符。

例子:

    msgget(key, IPC_CREAT|TPC_EXCL|0666);



2. msgsnd: --往消息队列中写消息包含库:

    #include <sys/types.h>

    #include <sys/ipc.h>

    #include <sys/msg.h>

函数原型:

    int msgsnd(int msqid, const void *msgp, size_t msgsz, int msg**);

参数:

    ①msqid,要操作的消息队列的标识符

    ②msgp,存放要发送的消息。

        定义要求:

             struct msgbuf {

               long mtype;       /* 消息的类型, must be > 0 */

               char mtext[1];    /* message data */

             };

    ③msgsz,发送的消息的正文的长度(除去消息类型之外的)。

        sizeof(struct msgbuf) - sizeof(long);

    ④msg**,决定了消息的发送是否是阻塞方式

        IPC_NOWAIT,非阻塞

        0,阻塞,直到发送成功

返回值:

    成功 0

    失败 -1



3. msgrcv: --读取消息或接收一条消息头文件:

    #include <sys/types.h>

    #include <sys/ipc.h>

    #include <sys/msg.h>

函数原型:

    ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,

                      int msg**);

参数:

    ①msqid,要读取的消息队列

    ②msgp,接收消息的缓冲区

        定义要求:

             struct msgbuf {

               long mtype;       /* 消息的类型, must be > 0 */

               char mtext[1];    /* message data */

             };

    ③msgsz,要接收消息的正文的长度

    ④msgtyp,要读取的消息队列中消息的类型

            0,表示读取消息队列中的第一条消息

            >0,表示读取消息队列中类型为msgtype的消息

            <0,接收消息队列中类型值不小于msgtyp 的绝对值且类型值又最小的消息。

   ⑤msg**,决定了消息的接收是否是阻塞方式        IPC_NOWAIT,非阻塞

        0,阻塞,直到有对应的消息

返回值:

    成功 读到消息正文的字节个数

    失败 -1





4. msgctl: --控制函数库:

    #include <sys/types.h>

    #include <sys/ipc.h>

    #include <sys/msg.h>

原型:

    int msgctl(int msqid, int cmd, struct msqid_ds *buf);

参数:

    msgid,要操作的消息队列的标识符

    cmd,

            IPC_STAT  (获取对象属性), 存放在第三参数中

            IPC_SET (设置对象属性),第三个参数存放将要设置的属性

            IPC_RMID (删除对象), 此时第三个参数为NULL。

返回值:

    成功,0

    失败,-1

__________________________________________________________________________________________

共享内存:ftok

2. shmget    创建/打开共享内存

3. shmat    获得一个共享内存的映射地址

4. shmdt    接触映射

5. shmctl    共享内存的控制(获取、设置、删除)





1. ftok:--获得一个key值包括的库:

     #include <sys/types.h>

     #include <sys/ipc.h>

函数原型:

    key_t ftok(const char *pathname, intproj_id);

参数:

    pathname,文件名

    proj_id,是子序号。虽然是int类型,但是只使用8bits(1-255)

例子:



2. shmget:--创建/打开共享内存包含库:

    #include <sys/ipc.h>

    #include <sys/shm.h>

函数原型:

    int shmget(key_tkey, size_tsize, int shm**);



参数:

    ①key, 用来使不同进程使用相同的共享内存,键值用来区分不同的共享内存

         IPC_PRIVATE:表示申请的共享内存是私用的。

           key = ftok(xxx); 需要通过ftok函数来获得。

   ②size:进程要申请的共享内存的大小(字节)

   ③shm**:

        IPC_CREAT,创建

        IPC_EXCL,如果有错误,指出

     指定的共享内存的权限:IPC_CREAT|IPC_EXCL| 0666

返回值:

    成功,返回 获得的共享内存的标识符。

    失败, 返回 -1.  

用法:

    int shmid;

    key = ftok(".", 'a');  

    shmid = shmget(key, 1000,IPC_CREAT|IPC_EXCL|0666); 创建

    shmid = shmget(key, 1000,0666)打开共享内存:



3. shmat: --获得一个共享内存的映射,返回一个指向共享内存的指针,函数原型:

    void *shmat(intshmid, const void *shmaddr, int shm**);

参数:  

    ①shmid,共享内存标识符

    ②shmaddr,为 NULL表示让系统为用户自动分配内存

           非NULL 用户自定义空间

    ③shm**,

        SHM_RDONLY   表示对共享内存的操作,只可以读。

        0  表示可读可写

返回值:

    成功,返回映射后的地址。需要强制类型转换

    失败,返回NULL。



4. shmdt:--解除映射。 函数原型:

    int shmdt(const void *shmaddr);

参数:

    就是shmat的返回值

返回值:

    0,成功

    -1,失败



5. shmctl:--共享内存的控制函数 包含头文件:

    #include <sys/shm.h>

函数原型:

    int shmctl(intshmid, intcmd, struct shmid_ds *buf);

参数:

     ①shmid: 要操作的共享内存的标识符

     ②cmd:   

            IPC_STAT  (获取对象属性), 存放在第三参数中

            IPC_SET (设置对象属性),第三个参数存放将要设置的属性

            IPC_RMID (删除对象), 此时第三个参数为NULL。

返回值:

    0,成功

    -1,失败

__________________________________________________________________________________________





信号量:--也叫system V的信号灯集:  一种计数信号灯1. semget    创建/打开一个信号量 集合

2. semctl    对信号量的集合的控制

3. semop    信号量集合的 PV 操作





1. semget: --创建/打开一个信号灯集合库:

     #include <sys/types.h>

     #include <sys/ipc.h>

     #include <sys/sem.h>

原型:

    int semget(key_tkey, intnsems, int sem**);

参数:

    ①key,ftok获得值

    ②nsems,表示要申请的信号灯集合中包含的信号量的个数

    ③sem**,

        IPC_CREAT

        IPC_EXCL

例子:

    semget(key, 2, IPC_CREAT|IPC_EXCL|0666);

返回:

    成功,返回一个信号灯集合的标识符    -->是 semid

    失败 -1



2. semctl: --对信号灯集合的控制库:

     #include <sys/types.h>

       #include <sys/ipc.h>

       #include <sys/sem.h>

原型:

    int semctl(intsemid, intsemnum, int cmd, ...);

参数:

    ①semid,

    ②semnum,要操作该集合中信号量的编号,信号量的编号从0开始。

    ③cmd,

        GETVAL,获取信号灯的值

        SETVAL,设置信号灯的值                   semctl(semid, 0, SETVAL, 共用体);

        IPC_RMID,从系统中删除信号灯集合 semctl(semid, 0, IPC_TMID);--随便删除哪一个,都能把所有的删除

    ④第四个参数,看命令字需要不需要,且内容可以是一个和多个

                union semun {

                       int              val;                /* Value for SETVAL */

                       struct semid_ds *buf;     /* Buffer for IPC_STAT, IPC_SET */

                       unsigned short  *array;  /* Array for GETALL, SETALL */

                       struct seminfo  *__buf;   /* Buffer for IPC_INFO

                                                                       (Linux-specific) */

                       };

返回值:

    成功 0

    失败 -1



3. semop: --信号灯集合的 PV 操作库:

    #include <sys/types.h>

    #include <sys/ipc.h>

    #include <sys/sem.h>

原型:

    int semop(int semid, struct sembuf *opsptr, size_tnops);

参数:

    ①semid,

    ②opsptr,

        struct sembuf{        --注意,这个结构体不需要自己定义,可直接用

             unsigned short sem_num;  /* semaphore number */ //要操作的信号量的编号

             short          sem_op;   /* semaphore operation */ //要执行的PV操作

             short          sem_**;  /* operation flags */

            };

        sem_num成员,要操作的信号量的编号

        sem_op成员,

            0等待,直到信号灯的值变成0

            >0,表示信号量的值要增加 semop 个,相当于V

            <0,表示信号量的值要减少 semop 个,相当于P

        sem_flag,

            0,semop函数阻塞操作

            IPC_NOWAIT,非阻塞,,,

            SEM_UNDO(不常用),

    ③nops,semop函数执行一次要操作的

返回值:

    成功 0

    失败 -1












通信

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

397

主题

401

帖子

0

粉丝