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

 

一、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 msgflg);
参数:
    ①key,ftok获得的值
    ②msgflg,
        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 msgflg);
参数:
    ①msqid,要操作的消息队列的标识符
    ②msgp,存放要发送的消息。
        定义要求:
             struct msgbuf {
               long mtype;       /* 消息的类型, must be > 0 */
               char mtext[1];    /* message data */
             };
    ③msgsz,发送的消息的正文的长度(除去消息类型之外的)。
        sizeof(struct msgbuf) - sizeof(long);
    ④msgflg,决定了消息的发送是否是阻塞方式
        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 msgflg);
参数:
    ①msqid,要读取的消息队列
    ②msgp,接收消息的缓冲区
        定义要求:
             struct msgbuf {
               long mtype;       /* 消息的类型, must be > 0 */
               char mtext[1];    /* message data */
             };
    ③msgsz,要接收消息的正文的长度
    ④msgtyp,要读取的消息队列中消息的类型
            0,表示读取消息队列中的第一条消息
            >0,表示读取消息队列中类型为msgtype的消息
            <0,接收消息队列中类型值不小于msgtyp 的绝对值且类型值又最小的消息。
   ⑤msgflg,决定了消息的接收是否是阻塞方式
        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, int proj_id);
参数:
    pathname,文件名
    proj_id,是子序号。虽然是int类型,但是只使用8bits(1-255)
例子:
 

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

包含库:
    #include <sys/ipc.h>
    #include <sys/shm.h>
函数原型:
    int shmget(key_t key, size_t size, int shmflg);
参数:
    ①key, 用来使不同进程使用相同的共享内存,键值用来区分不同的共享内存
         IPC_PRIVATE:表示申请的共享内存是私用的。
           key = ftok(xxx); 需要通过ftok函数来获得。
   ②size:进程要申请的共享内存的大小(字节)
   ③shmflg: 
        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(int shmid, const void * shmaddr, int shmflg);
参数:  
    ①shmid,共享内存标识符
    ②shmaddr,为 NULL表示让系统为用户自动分配内存
           非NULL 用户自定义空间
    ③shmflg,
        SHM_RDONLY   表示对共享内存的操作,只可以读。
        0  表示可读可写
返回值:
    成功,返回映射后的地址。需要强制类型转换
    失败,返回NULL。
 

4. shmdt:--解除映射。 

函数原型:
    int shmdt(const void * shmaddr);
参数:
    就是shmat的返回值
返回值:
    0,成功
    -1,失败
 

5. shmctl:--共享内存的控制函数 

包含头文件:
    #include <sys/shm.h>
函数原型:
    int shmctl(int shmid, int cmd, 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_t key, int nsems, int semflg);
参数:
    ①key,ftok获得值
    ②nsems,表示要申请的信号灯集合中包含的信号量的个数
    ③semflg,
        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(int semid, int semnum, 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_t nops);
参数:
    ①semid,
    ②opsptr,
         struct sembuf{        -- 注意,这个结构体不需要自己定义,可直接用
             unsigned short sem_num;  /* semaphore number */ //要操作的信号量的编号
             short          sem_op;   /* semaphore operation */ //要执行的PV操作
             short          sem_flg;  /* 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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值