文章目录
  1. 1. 一.共享内存示意图↓
  2. 2. 二.地址映射示意图↓(APUE):
  3. 3. 三.共享内存的数据结构shmid_ds
  4. 4. 四.共享内存操作接口
  5. 5. 五.注意事项
  6. 6. 六.示例代码

共享内存允许两个进程共享一个给定的存储区。所以数据不需要在两个进程间复制。这是最快的一种IPC。
头文件:sys/shm.h

一.共享内存示意图↓

内存示意图

二.地址映射示意图↓(APUE):

地址映射示意图

三.共享内存的数据结构shmid_ds

1
2
3
4
5
6
7
8
9
10
11
struct shmid_ds {
struct ipc_perm shm_perm; /* see Section 15.6.2 */
size_t shm_segsz; /* size of segment in bytes */
pid_t shm_lpid; /* pid of last shmop() */
pid_t shm_cpid; /* pid of creator */
shmatt_t shm_nattch; /* number of current attaches */
time_t shm_atime; /* last-attach time */
time_t shm_dtime; /* last-detach time */
time_t shm_ctime; /* last-change time */
.....
};

四.共享内存操作接口

  1. 创建:shmget()
  2. 控制:shmctl()
  3. 挂载映射:shmat()
  4. 分离:shmdt()
  5. 删除:shmctl(shm_id,IPC_RMID,0)

五.注意事项

  1. 进程操作共享内存区,要注意同步问题,可用信号量来同步。
  2. 根据进程知识,fork一个子进程,它继承父进程挂载的共享内存。
  3. 如果用exec执行新程序,则挂载的共享内存将被卸载。
  4. 如果进程调用exit(),则挂载的共享内存与进程脱离关系。

六.示例代码

利用信号量来给共享内存区同步。
发送端:如果信号量为0,往共享区写数据,将信号量加1;
接收端:如果信号量为1,读出共享区数据,将信号量减1。
如果接收到“end”,则删除共享内存,信号量。通信结束。

发送端代码:(为了简洁没有做错误处理)

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
//shm_sem_sender.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <string.h>

int main(int argc,char *argv[])
{

int running = 1;
int shmid;
int semid;
int value;
void *share_memp=NULL;
struct sembuf sem;
sem.sem_num=0;
sem.sem_flg=SEM_UNDO;
semid=semget((key_t)123456,1,0666|IPC_CREAT);
//设置信号初始值为0
semctl(semid,0,SETVAL,0);

shmid=shmget((key_t)654321,(size_t)2048,0600|IPC_CREAT);
share_memp = shmat(shmid,NULL,0);
while(running)
{
value=semctl(semid,0,GETVAL);
if(value==0)
{
printf("write data operate\n");
printf("please input:");
scanf("%s",(char *)share_memp);
sem.sem_op=1;
semop(semid,&sem,1);
}
if(strcmp(share_memp,"end")==0)
running--;
}
shmdt(share_memp);
return 0;
}

接收端代码:(为了简洁没有做错误处理)

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
//shm_sem_recv.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <string.h>

int main(int argc,char *argv[])
{

int running = 1;
int shmid;
int semid;
int value;
void *share_memp=NULL;
struct sembuf sem;
sem.sem_num=0;
sem.sem_flg=SEM_UNDO;
semid=semget((key_t)123456,1,0666|IPC_CREAT);
//设置信号初始值为0
semctl(semid,0,SETVAL,0);

shmid=shmget((key_t)654321,(size_t)2048,0600|IPC_CREAT);
share_memp = shmat(shmid,NULL,0);
while(running)
{
value=semctl(semid,0,GETVAL);
if(value==1)
{
printf("read data operate\n");
sem.sem_op=-1;
semop(semid,&sem,1);
printf("%s",(char *)share_memp);
}
if(strcmp(share_memp,"end")==0)
running--;
}
shmdt(share_memp);
shmctl(shmid,IPC_RMID,0);
semctl(semid,IPC_RMID,0);
return 0;
}

文章目录
  1. 1. 一.共享内存示意图↓
  2. 2. 二.地址映射示意图↓(APUE):
  3. 3. 三.共享内存的数据结构shmid_ds
  4. 4. 四.共享内存操作接口
  5. 5. 五.注意事项
  6. 6. 六.示例代码