- IPC(Inter-Process Communication)进程间通信,提供了各种进程间通信的方法。在Linux C编程中有几种方法
- (1) 半双工Unix管道
- (2) FIFOs(命名管道)
- (3) 消息队列
- (4) 信号量
- (5) 共享内存
- (6) 网络Socket
消息队列
消息队列是在消息的传输过程中保存消息的容器。消息队列管理器在将消息从它的源中继到它的目标时充当中间人
。队列的主要目的是提供路由并保证消息的传递;如果发送消息时接收者不可用,消息队列会保留消息,直到可以成功地传递它。
消息队列提供了一个从一个进程向另一个进程发送消息的方法。
消息队列结构体(/usr/include/linux/msg.h)
struct msqid_ds {
struct ipc_perm msg_perm;
struct msg *msg_first; /* first message on queue,unused */
struct msg *msg_last; /* last message in queue,unused */
__kernel_time_t msg_stime; /* last msgsnd time */
__kernel_time_t msg_rtime; /* last msgrcv time */
__kernel_time_t msg_ctime; /* last change time */
unsigned long msg_lcbytes; /* Reuse junk fields for 32 bit */
unsigned long msg_lqbytes; /* ditto */
unsigned short msg_cbytes; /* current number of bytes on queue */
unsigned short msg_qnum; /* number of messages in queue */
unsigned short msg_qbytes; /* max number of bytes on queue */
__kernel_ipc_pid_t msg_lspid; /* pid of last msgsnd */
__kernel_ipc_pid_t msg_lrpid; /* last receive pid */
};
消息队列在内核中的表示
系统内核能够创建多少个消息队列?(cat /proc/sys/kernel/msgmni)
每个消息队列能够装多少字节?(cat /proc/sys/kernel/msgmnb)
队列中一条记录最大为多大?(at /proc/sys/kernel/msgmax)
创建消息队列
-
int msgget(key_t key, int msgflg);
- key: 标识某个消息队列的名字
-
msgflg: 由九个权限标志构成,它们的⽤用法和创建⽂文件时使⽤用的mode模式标志是一样的
返回值:成功返回消息队列的标识码,失败返回 -1
查看消息队列
-
ipcs -q
往消息队列写数据
-
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
- 参数:
- msgid: 由msgget函数返回的消息队列标识码
- msgp:是.一个指针,指针指向准备发送的消息
- msgsz:是msgp指向的消息.长度,这个.长度不含保存消息类型的那个long int.长整型
- msgflg:控制着当前消息队列满或到达系统上限时将要发生的事情
- msgflg=IPC_NOWAIT表.示队列满不等待,返回EAGAIN错误。
- 返回值:
- 成功返回0;失败返回-1
从消息队列读数据
-
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
- 参数:
- msgid: 由msgget函数返回的消息队列标识码
- msgp:是⼀一个指针,指针指向准备接收的消息
- msgsz:是msgp指向的消息⻓长度,这个⻓长度不含保存消息类型的那个long int⻓长整型
- msgtype:它可以实现接收优先级的简单形式
- msgflg:控制着队列中没有相应类型的消息可供接收时将要发⽣生的事
- 返回值:
- 成功返回实际放到接收缓冲区⾥里去的字符个数,失败返回-1
删除消息队列
- 命令行手动删除:
-
ipcrm [ -Q key | -q id ];
- 在程序中删除消息队列:
-
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
- 参数
- msqid: 由msgget函数返回的消息队列标识码
-
cmd:是将要采取的动作,(有三个可取值)
cmd有三个参数: -
命令 说明 IPC_STAT 把msqid_ds结构中的数据设置为消息队列的当前关联值 IPC_SET 在进程有足够权限的前提下,把消息队列的当前关联值设置为msqid_ds数据结构中给出的值 IPC_RMID 删除消息队列 - 返回值:
- 成功返回0,失败返回-1
消息队列代码示例
struct msgbuf //存放消息的结构体
{
long channal;
char buf[1024];
};
int main()
{
key_t key = ftok(".",'a'); //产生key值
int msgid = msgget(key,IPC_CREAT); //创建消息队列
if(msgid==-1)
perror("msgget"),exit(1);
struct msgbuf mb;
fgets(mb.buf,1024,stdin); //写内容到buf中
int len = strlen(mb.buf);
if(msgsnd(msgid,&mb,len,0)==-1) //把数据发送到消息队列中
perror("msgsnd"),exit(1);
struct msgbuf rcv;
if(msgrcv(msgid,&rcv,len,0,0)==-1)//从消息队列中读出数据
perror("msgrcv"),exit(1);
printf("%s\n",rcv.buf);
msgctl(msgid,IPC_RMID,0); //删除消息队列
return 0;
}