消息队列
·消息队列提供了从一个进程向另一个进程发送一块数据的方法;
·每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值;
·消息队列也具有管道的缺点,即每个消息的最大长度是有上限的,每个消息队列的总的字节数是有上限的,系统上消息队列的总数也有一个上限。
消息队列在内核中的表示
消息队列函数
1、创建和访问消息队列
函数原型:int msgget(key_t key,int msgflg);
参数:key:消息队列的名字;
msgflg: 创建时为:IPC_CREAT | 0644(权限)
打开时为:0
返回值:成功返回消息队列的标识码;失败返回-1.
创建一个消息队列msg.c的代码如下:
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<sys/ipc.h>
4 #include<sys/msg.h>
5
6 int main()
7 {
8 int id = msgget(1234,IPC_CREAT | 0644);
9 if(id == -1)
10 {
11 perror("msgget");
12 exit(1);
13 }
14 printf("creat ok!\n");
15 }
2、查看消息队列: ipcs -q
3、消息队列的控制函数
函数原型:int msgctl(int msgid,int cmd,struct msgid_ds *buf);
参数:msqid:由msgget函数返回的消息队列标识码;
cmd:将要采取的动作;
返回值:成功返回0,失败返回-1.
4、把一条消息添加到消息队列中
函数原型:int msgsnd(int msgid, const void *msgp, size_t msgsz, int msgflg);
参数: msgid:由msgget函数返回的消息队列标识码;
msgp:是一个指针,指向准备发送的消息;
msgsz:是msgp指向的消息长度,该长度不包含保存消息类型的long int长整型;
msgflag:一般设为0.
返回值:成功返回0;失败返回-1.
将消息添加到消息队列中的代码如下:
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<sys/ipc.h>
4 #include<sys/msg.h>
5 #include<string.h>
6
7 struct msgbuf{
8 long type;
9 char text[1];
10 }
11
12 int main()
13 {
14 int id = msgget(1234,0);
15 struct msgbuf sm;
16 printf("channel:");
17 scanf("%d",&sm.type);
18 printf("text:");
19 scanf("%s",sm.text);
5、从一个消息队列接收消息
函数原型:ssize_t msgrcv(int msgid, void *msgp, size_t msgsz, long msgtype, int msgflg);
参数: msgid:由msgget函数返回的消息队列标识码;
msgp:是一个指针,指向准备接收的消息;
msgsz:是msgp指向的消息长度,该长度不包含保存消息类型的long int长整型;
msgtype:类型号
msgflag:一般设为0.
返回值:成功返回接收的字符个数;失败返回-1.
6、删除消息队列 :
ipcrm -Q key
共享内存
共享内存是最快的进程间通信。(进程不再通过执行进入内核的系统调用来传递彼此的数据)
共享内存示意图
共享内存函数
1、创建/打开共享内存
原型:int shmget(key_t key, size_t size, int shmflg);
参数:key: 共享内存段的名字;
size:共享内存大小;
shmflg:创建:IPC_CREAT | 0644(权限);
打开:0
返回值:成功返回标识码;失败返回-1.
2、将共享内存映射到自己的地址空间
原型:void* shmat(int shmid, const void* shmaddr, int shmflg);
参数:shmid: 共享内存标识;
shmaddr:指定映射的地址;
shmflg:一般为0.
返回值:成功返回指向映射到的虚拟地址空间的起始位置的指针;失败返回-1.
3、将共享内存段与当前进程脱离
原型:int shmdt(const void* shmaddr);
参数:shmaddr:由shmat所返回的指针。
返回值:成功返回0;失败返回-1.
4、控制共享内存
原型:int shmctl(int shmid, int cmd, struct shmid_ds *buf);
参数:shmid:由shmget返回的共享内存标识码;
cmd:将要采取的动作;
buf:指向一个保存着共享内存的模式状态和访问权限的数据结构
返回值:成功返回0;失败返回-1.
共享内存有关函数的测试代码:
Makefile
1 .PHONY:all
2 all:server client
3
4 client:client.c comm.c
5 gcc -o $@ $^
6 server:server.c comm.c
7 gcc -o $@ $^
8 .PHONY:clean
9 clean:
10 rm -f client server
comm.h
1 #ifndef _COMM_H_
2 #define _COMM_H_
3
4 #include<stdio.h>
5 #include<sys/types.h>
6 #include<sys/ipc.h>
7 #include<sys/shm.h>
8
9 #define PATHNAME "."
10 #define PROJ_ID 0x6666
11
12 int createshm(int size);
13 int destroyshm(int shmid);
14 int getshm(int size);
15
16 #endif
~
comm.c
1 #include"comm.h"
2
3 static int commshm(int size,int flags)
4 {
5 key_t _key = ftok(PATHNAME,PROJ_ID);
6 if(_key < 0)
7 {
8 perror("ftok");
9 return -1;
10 }
11 int shmid = 0;
12 if((shmid = shmget(_key,size,flags)) < 0)
13 {
14 perror("shmget");
15 return -2;
16 }
17 return shmid;
18 }
19
20 int destoryshm(int shmid)
21 {
22 if(shmctl(shmid,IPC_RMID,NULL) < 0)
23 {
24 perror("shmctl");
25 return -1;
26 }
27 return 0;
28 }
29
30 int createshm(int size)
31 {
32 return commshm(size,IPC_CREAT | IPC_EXCL | 0666);
33 }
34
35 int getshm(int size)
36 {
37 return commshm(size,IPC_CREAT);
38 }
server.c
1 #include "comm.h"
2
3 int main()
4 {
5 int shmid = createshm(4096);
6 char *addr = shmat(shmid,NULL,0);
7 sleep(2);
8 int i = 0;
9 while(i++ < 26)
10 {
11 printf("client# %s\n",addr);
12 sleep(1);
13 }
14 shmdt(addr);
15 sleep(2);
16 destoryshm(shmid);
17 return 0;
18 }
client.c
1 #include "comm.h"
2
3 int main()
4 {
5 int shmid = getshm(4096);
6 sleep(1);
7 char *addr = shmat(shmid,NULL,0);
8 sleep(2);
9 int i = 0;
10 while(i < 26)
11 {
12 addr[i] = 'A'+i;
13 i++;
14 addr[i] = 0;
15 sleep(1);
16 }
17 shmdt(addr);
18 sleep(2);
19 return 0;
20 }