您的位置:首页 > 运维架构 > Linux

进程间通信---管道

2018-03-12 20:18 239 查看
我们知道,进程的用户空间是互相独立的,一般而言是不能互相访问的,唯一的例外是共享内存区。但是,系统空间却是“公共场所”,所以内核显然可以提供这样的条件。所以进程之间交换数据时在内核进行,通俗的说A进程把数据拷贝到内核,B进程从内核中把数据读走,我们把内核提供的这种机制叫做进程间通信,(IPC)。

一、管道(pipe)

管道是Unix中最古老的进程间通信的形式。 我们把从一个进程连接到另一个进程的一个数据流称为一个“管道”。

管道是一种基本的ipc机制,由pipe函数创建,如下:



调用pipe函数时在内核中开辟一块缓冲区(管道)用于通信,它有一个读端和一个写端。

fd:文件描述符数组,其中fd[0]表示读端, fd[1]表示写端

pipe函数调用成功返回0,失败返回-1。

二、如何实现进程间通信







(1)首先父进程调用pipe开通管道,得到两个文件描述符指向管道的两端

(2)父进程通过fork创建子进程,那么同样的子进程也有两个文件描述符指向管道的两端

(3)父进程关闭fd[0],子进程关闭管道fd[1],这样父进程向管道写数据,子进程向管道读数据,这就实现了进程的通信.

注:图中0、1、2分别指的是标准输入,标准输出,标准出错

三、匿名管道和命名管道

1、匿名管道

值得说明的是,匿名管道只能实现亲缘关系进程之间通信,而不能实现任意两个本地进程之间的通信

使用,正如上图所示:

在父进程中,首先创建这个匿名管道,然后fork创建子进程,关闭子进程的读端,子进程只能进行写,子进程向这个匿名管道里面写数据,父进程向这个匿名管道里面读数据,以此来实现进程间的通信。

实现:

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<unistd.h>
#include<string.h>
#include<sys/wait.h>

int main()
{
int fds[2] ={0};
if(pipe(fds)<0)
{
perror("pipe");
return 1;
}
pid_t id =fork();
if(id==0)
{
//子进程写
close(fds[0]);
char *msg ="hello pipe,i am a child!";
while(1)
{
write(fds[1],msg,strlen(msg));
sleep(1);
}
exit(0);//退出
}
else{
//父进程读
close(fds[1]);
char buf[1024];
while(1)
{
ssize_t ret = read(fds[0],buf,sizeof(buf)-1);
if(ret>0)
{
buf[ret-1]=0;
printf("client->father:%s\n",buf);
}
}
pid_t tmp =wait(NULL);
}
return 0;
}




2、命名管道

如果想在不相关的进程之间通信,可以使用FIFO文件来做这项工作,它经常被称为命名管道 。

FIFO总是按照先进先出的原则工作,也就是第一个被写入的数据将首先从管道中读出 。

那么如何创建呢?

方法一:命名管道可以从命令行创建,方法是使用命令:

$ mkfifo filename

方法二:从在程序使用系统函数创建,函数有:

int mkfifo(const char *filename,mode_t mode);

以mkfifo为例:

int main(int argc, char *argv[])
{
mkfifo("p2", 0644);
return 0;
}


eg-用命名管道实现server&client通信 :

(1)、编写Makefife文件:



(2)、server.c用来读数据(读端)



(3)、client.c向管道写数据(写端):



结果:



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux 管道 通信