进程-消息队列与共享内存

消息队列
消息队列就是一个消息的列表,进程可以在消息队列中添加消息和读取消息
消息队列具有一定的FIFO特性,具有无名管道与有名管道的各自的优势,可以支持任意两个进程的进程间通讯

创建消息队列
用法

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
//key : 由 ftok 函数合成
//msgflg : 消息队列标志

删除消息队列
int msgctl(int msqid, int cmd, struct msqid_ds *buf);

发送消息

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
/*
msqid : 消息队列 ID
msgp : 消息结构体指针
msgsz : 消息内容的长度
msgflg : 消息队列标志<span class="bd-box"><h-char class="bd bd-beg"><h-inner>,</h-inner></h-char></span>默认可以填 0
IPC_NOWAIT : 可以设置非阻塞
*/

接收消息

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
/*
msqid : 消息队列 id
msgp : 消息结构指针
msgtyp : 消息类型
msgflg : 消息队列标志<span class="bd-box"><h-char class="bd bd-beg"><h-inner>,</h-inner></h-char></span>默认可以填0
IPC_NOWAIT : 可以设置非阻塞
*/

共享内存
共享内存是将分配的物理空间直接映射到进程的用户虚拟地址空间中,减少数据在内核空间缓存
共享内存是一种效率较高的进程间通讯的方式
共享内存创建

#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
//创建一个共享内存,并返回 ID

共享内存删除

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

共享内存映射

#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);//将进程地址空间映射到共享内存上

共享内存解除映射

int shmdt(const void *shmaddr);//解除进程地址空间与共享内存的映射

完整代码
shm_write.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define PATHNAME "."
#define PRO_ID 100

#define SZ 256


int main(void)
{
key_t key;
int shmid,ret;
void *addr = NULL;

key = ftok(PATHNAME,PRO_ID);
if(key == -1){
perror("[ERROR] key(): ");
exit(EXIT_FAILURE);
}

shmid = shmget(key,SZ,IPC_CREAT|0666);
if(shmid == -1){
perror("shmid(): ");
exit(EXIT_FAILURE);
}

printf("shmid = %d\n",shmid);
addr = shmat(shmid, NULL, 0);
if (addr == (void *)-1){
perror("[ERROR] shmat(): ");
return -1;
}

memset(addr,'A',10);

shmdt(addr);

return 0;
}


shm_read.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define PATHNAME "."
#define PRO_ID 100

#define SZ 256


int main(void)
{
key_t key;
int shmid,ret,i;
char buffer[10] = {0};
void *addr = NULL;

key = ftok(PATHNAME,PRO_ID);
if(key == -1){
perror("[ERROR] key(): ");
exit(EXIT_FAILURE);
}

shmid = shmget(key,SZ,IPC_CREAT|0666);
if(shmid == -1){
perror("shmid(): ");
exit(EXIT_FAILURE);
}

printf("shmid = %d\n",shmid);
addr = shmat(shmid, NULL, 0);
if (addr == (void *)-1){
perror("[ERROR] shmat(): ");
return -1;
}

memcpy(buffer,addr,10);

for (i = 0;i < 10;i++){
printf(" %c ",buffer[i]);
}

putchar('\n');


shmdt(addr);

return 0;
}