题目 父子进程通过共享内存进行通信。
共享内存原理知识和开发
共享内存特点
- 最高效的进程间通信方式,进程可以直接读写内存,不需要任何数据的拷贝
- 多进程通信过程中。内核分配有共同的内存区,需要访问的进程可以将其映射到自己的私有地址空间。
- 但是需要依靠互斥锁或者信号量来保证同步性。防止阻塞。
共享内存实现:
(1)、创建共享内存 shmget();
(2)、映射共享内存。 Shmat()
(3)、撤销共享内存映射 shmdt()
(4)、删除共享内存对象。Shmctl()
比如:父进程收到信号SIGUSR1,写共享内存。
子进程收到信号SIGUSR2,读共享内存
流程如下:
1、先求key的值
2、创建并打开共享内存
3、映射
4、创建 父子子进程
5、父进程中安装信号 写入数据然后给子进程发送信号,等待子进程的信号 然后读取数据
6、子进程中安装信号 等待父进程写数据 父进程写完发出的数据被子进程接收到 ,然后子进程开始读取数据,然后再给共享内存中写入数据,再发送信号给父进程
7、解除映射。删除共享内存
代码如下
/*************************************************************************
> File Name: 1.c
> Author:
> Mail:
> Created Time: 2018年06月11日 星期一 18时26分47秒
************************************************************************/
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<signal.h>
#include<unistd.h>
#define BUF_SIZE 100
#define SHM_SIZE 1024
void handler1(int sig)
{
if ( SIGUSR1 == sig )
{
printf("\t\t父进程已经写好数据\r\n");
}
}
void handler2(int sig)
{
if ( SIGUSR2 == sig )
{
printf("\t\t子进程已经写好数据\r\n");
}
}
int main(void)
{
key_t key = 0;
int ret = 0;
int shmid = 0;
pid_t pid;
char * pShm = NULL;
char buf[BUF_SIZE] = {'\0'};
//key
key = ftok( "/tmp", 23 );
if ( 0 > key )
{
perror("ftok error");
return -1;
}
//创建并且打开共享内存
shmid = shmget(key, SHM_SIZE, 0644 | IPC_CREAT);
if ( 0 > shmid )
{
perror("shmget error");
return -1;
}
//映射
pShm = shmat(shmid, NULL, 0);
if ( (void *)-1 == pShm )
{
perror("shmat error");
shmctl(shmid, IPC_RMID, NULL);
return -1;
}
//创建子进程
pid = fork();
if ( 0 > pid )
{
perror("fork error");
shmctl(shmid, IPC_RMID, NULL);
return -1;
}
else if ( 0 < pid )
{
//安装信号
signal(SIGUSR2, handler2);
while(1)
{
printf("父进程对子进程说:");
//向共享内存中写入数据
fgets(pShm, SHM_SIZE, stdin);
//数据写入完成,向子进程发送信号
kill(pid,SIGUSR1);
//等待子进程信号
pause();
//读取共享内存中数据
printf("父进程读取:%s\r\n",pShm);
//输入#时结束父程序,并向子进程发送信号
if ( '#' == pShm[0] )
{
kill(pid, SIGUSR1);
break;
}
}
printf("父进程结束!\n");
//映射
shmdt(pShm);
//删除共享内存
shmctl(shmid, IPC_RMID, NULL);
}
else
{
//获取父进程ID
pid_t ppid;
ppid = getppid();
//安装信号
signal(SIGUSR1, handler1);
//等待父进程信号
while(1)
{
//等待父进程写数据
pause();
//读取输出共享内存中的数据
printf("子进程读取:%s\r\n",pShm);
printf("子进程对父进程说:");
//向共享内存写入数据
fgets(pShm, SHM_SIZE, stdin);
//数据写入完成,向父进程发送信号
kill(ppid,SIGUSR2);
//输入#时结束父程序,并向子进程发送信号
if ( '#' == pShm[0] )
{
kill(ppid, SIGUSR2);
break;
}
}
printf("子进程结束!\n");
}
return 0;
}