进程间通信(inter process communication) IPC学习笔记

利用进程间通信IPC中的三个对象:共享内存信号灯数组消息队列,解决并发进程同步互斥的问题

  • 共享内存是 OS 内核为并发进程间交换数据而提供的一块内存区(段)。如果段
    的权限设置恰当,每个要访问该段内存的进程都可以把它映射到自己私有的地址空
    间中。如果一进程更新了段中数据,那么其他进程立即会看到这一更新。进程创建
    的段也可由另一进程读写。  (ipcs -m)
  • 信号灯数组是 OS 内核控制并发进程间共享资源的一种进程同步与互斥机制。   (ipcs -s)
  • 消息队列是 OS 内核控制并发进程间共享资源的另一种进程同步机制。   (ipcs -q)

 在权限允许的情况下您可以使用 ipcrm 命令删除系统当前存在的 IPC 对象中的任一个对象。

ipcrm -m 21482
 删除标号为 21482 的共享内存。
ipcrm -s 32673
 删除标号为 32673 的信号灯数组。
ipcrm -q 18465
 删除标号为 18465 的消息队列。
在 linux 的 proc 文件系统中有 3 个虚拟文件动态记录了由以上 ipcs 命令显示的
当前 IPC 对象的信息,它们分别是:
  • /proc/sysvipc/shm 共享内存
  • /proc/sysvipc/sem 信号量
  • /proc/sysvipc/msg 消息队列

创建共享内存

#include <sys/shm.h>
int shmget(key_t key,int size,int flags);
key 共享内存的键值,可以为 IPC_PRIVATE,也可以用整数指定一个
size 共享内存字节长度
flags 共享内存权限位。
shmget 调用成功后,如果 key 用新整数指定,且 flags 中设置了 IPC_CREAT位,则返回一个新建立的共享内存段标识符。
如果指定的 key 已存在则返回与 key关联的标识符。 不成功返回-1

令一段共享内存附加到调用进程

#include <sys/shm.h>
char *shmat(int shmid, char *shmaddr,int flags)
shmid 由 shmget 创建的共享内存的标识符
shmaddr 总为 0,表示用调用者指定的指针指向共享段
flags 共享内存权限位
shmat 调用成功后返回附加的共享内存首地址

令一段共享内存从调用进程中分离出去

#include <sys/shm.h>
int shmdt(char *shmadr);
shmadr 进程中指向附加共享内存的指针
shmdt 调用成功将递减附加计数,当计数为 0,将删除共享内存。调用不成功返回-1。


创建信号灯数组

#include <sys/sem.h>
int semget(key_t key,int nsems, int flags);
key 信号灯数组的键值,可以为 IPC_PRIVATE,也可以用整数指定一个
nsems 信号灯数组中信号灯的个数
flags 信号灯数组权限位。如果 key 用整数指定,应设置 IPC_CREAT 位。
semget 调用成功,如果 key 用新整数指定,且 flags 中设置了 IPC_CREAT 位,则
返回一个新建立的信号等数组标识符。 如果指定的整数 key 已存在则返回与 key 关联的标识符。 不成功返回-1

操作信号灯数组

#include <sys/sem.h>
int semop(int semid,struct sembuf *semop, unsigned nops);
semid 由 semget 创建的信号灯数组的标识符
semop 指向 sembuf 数据结构的指针
nops 信号灯数组元素的个数。
semop 调用成功返回 0,不成功返回-1。

控制信号灯数组

#include <sys/sem.h>
int semctl(int semid,int semnum,int cmd, union semun arg);
semid 由 semget 创建的信号灯数组的标识符
semnum 该信号灯数组中的第几个信号灯
cmd 对信号灯发出的控制命令。例如:
    GETVAL 返回当前信号灯状态
    SETVAL 设置信号灯状态
    IPC_RMD 删除标号为 semid 的信号灯
arg
 保存信号灯状态的联合体,信号灯的值是其中一个基本成员
union semun {
int val;  /* value for SETVAL */
......
};
semctl 执行不成功返回-1,否则返回指定的 cmd 的值。

创建消息队列

#include<sys/msg.h>
int msgget(key_t key,int flags)
key 消息队列的键值,可以为 IPC_PRIVATE,也可以用整数指定一个
flags 消息队列权限位。
msgget 调用成功,如果 key 用新整数指定,且 flags 中设置了 IPC_CREAT位,则返回一个新建立的消息队列标识符。 
如果指定的整数 key 已存在则返回与 key 关联的标识符。成功返回-1。

从到消息队列中读出一条新消息

#include <sys.msg.h>
int msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, long msgtype, int msgflg);
msqid 由消息队列的标识符
msgp 消息缓冲区指针。消息缓冲区结构为:
struct msgbuf {
long mtype;
 /* 消息类型,必须大于0 */
char mtext[1]; /* 消息数据,长度应于 msgsz 声明的一致*/
}
msgsz 消息数据的长度
msgtype 决定从队列中返回哪条消息:
    =0 返回消息队列中第一条消息
    >0 返回消息队列中等于 mtype 类型的第一条消息。
    <0 返回
     mtype<=type 绝对值最小值的第一条消息。
msgflg 为0表示阻塞方式,设置 IPC_NOWAIT 表示非阻塞方式
msgrcv 调用成功返回 0,不成功返回-1。

删除消息队列

int msgctl(int msqid, int cmd, struct msqid_ds *buf);
msqid
 由消息队列的标识符
cmd
 控制命令。常用的有:
IPC_RMID 删除 msgid 标识的消息队列
IPC_STAT 为非破坏性读,从队列中读出一个 msgid_ds 结构填充缓冲 buf
IPC_SET 改变队列的 UID,GID,访问模式和最大字节数。
msgctl 调用成功返回 0,不成功返回-1。



猜你喜欢

转载自blog.csdn.net/jemary_/article/details/80230984