常见的进程间通信方式
传统进程间通信方式
- 无名管道(pipe)
- 有名管道(fifo)
- 信号(signal)
System V IPC 对象
- 共享内存(share memory)
- 消息队列(message queue)
- 信号灯(semaphore)
System V IPC 对象
- 套接字(socket)
特点: - 只能用于具有血缘关系的进程间通信
- 半双工的通信模式,有固定的读端和写端fd[0]为读端 fd[1]为写端,fd为整形数组最小有两个元素
- 管道是一种特殊的文件,才在于内存中,在文件系统中不可见,可以用文件io函数来读写操作。如write(写)、read(读)。
无名管道的创建
父子进程间通信
/*************************************************************************
> 功能:利用无名管道实现两个具有血缘关系的进程通信
************************************************************************/
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
int main()
{
pid_t pid;
int fd[2];
int rd;
int wr;
char buf[1024]={0};
//创建无名管道
int ret=pipe(fd);
if(ret<0)
{
perror("pipe error");
exit(-1);
}
//创建子进程
pid= fork();
if(pid<0)
{
perror("fork error");
exit(-2);
}
//子进程读 /关闭写端close fd[1]
if(pid==0)
{
close (fd[1]);
if((rd=read(fd[0],buf,sizeof(buf))) > 0)
{
printf("无名管道读到的东西是%s\n",buf);
}
close(fd[0]);
exit(0);
}
//父进程写 /关闭读端 close fd[0]
if(pid>0)
{
memset(buf,0,sizeof(buf));
gets(buf);
close(fd[0]);
if( (wr=write(fd[1],buf,sizeof(buf)))>0)
{
printf("这次写进去了%s\n",buf);
waitpid(pid,NULL,0);
exit(0);
}
close(fd[1]);
}
exit(0);
}
兄弟进程间通信
/*************************************************************************
> File Name: pipe.c
> Author:
> 功能:利用无名管道实现两个具有血缘关系的进程通信
> Created Time: Tue 13 Aug 2019 08:12:22 PM PDT
************************************************************************/
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<wait.h>
int main()
{
pid_t pid;
pid_t pid1;
int fd[2];
int rd;
int wr;
char buf[1024]={0};
//创建无名管道
int ret=pipe(fd);
if(ret<0)
{
perror("pipe error");
exit(-1);
}
//创建子进程
pid= fork();
pid1=fork();
if(pid<0 || pid1<0)
{
perror("fork error");
exit(-1);
}
//子进程读 /关闭写端close fd[1]
if(pid==0)
{
close (fd[1]);
if((rd=read(fd[0],buf,sizeof(buf))) > 0)
{
printf("我是弟弟 ");
printf("无名管道是%s\n",buf);
}
close(fd[0]);
exit(10);
}
//子进程1写 /关闭读端close fd[0]
if(pid1==0)
{
memset(buf,0,sizeof(buf));
gets(buf);
close(fd[0]);
if( (wr=write(fd[1],buf,sizeof(buf)))>0)
{
printf("我是哥哥\n");
}
close(fd[1]);
exit(11);
}
//父进程
int status=0;
int status1=0;
if(pid>0)
{
sleep(1);
wait(&status);
printf("进程的退出状态是%d\n",WEXITSTATUS(status));
wait(&status1);
printf("进程1的退出状态是%d\n",WEXITSTATUS(status1));
}
exit(0);
}
无名管道使用需要注意的点
- 无名管道只能用在具有亲缘关系的进程间通信
- 是一种半双工的模式;意思是同一个时刻,只能读或者写;
- 只有在管道读端存在时,写端才有意义;
- 管道没有数据时,读端会一直阻塞;
- 读完数据就立马消失;
- 不能用fseek跳转;
- 只存在于内存中,在文件系统不可见;
- 遵循先进先出的规则。