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

Linux 进程通信(无名管道)

2016-09-01 14:41 309 查看
无名管道
无名管道是半双工的,就是对于一个管道来讲,只能读,或者写。
无名管道只能在相关的,有共同祖先的进程间使用(即一般用户父子进程)。
一个fork或者execve调用创建的子进程继承了父进程的文件描述符。


打开和关闭管道
int pipe(int filedes[2]);
在你从一个管道中读出或者写入数据,这个管道必须存在。
如果成功建立了管道,则会打开两个文件描述符,并把他们的值保存在一个整数数组中。
第一个文件描述符用于读取数据,第二个文件描述符用于写入数据。
管道的两个文件描述符相当于管道的两端,一端只负责读数据,一端只负责写数据
如果出错返回-1,同时设置errno
关闭一个文件描述符用close()函数
关闭一个管道的所有文件描述符等于关闭这个管道(不能读不能写)
pipe()函数打开管道一般不会失败


读写管道
读写管道与读写普通文件方式一样,调用write与read函数即可。
几乎不会在一个进程中打开一个管道仅供进程自己使用,管道是用来交换数据的。
因为一个进程已经能够访问它要通过管道共享的数据,和自己共享数据是没有意义的。
试图对一个管道的某一端同时进行读写操作是一个严重的错误。


//无名管道
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int arg, char * args[])
{
//定义文件描述符数组
int fdarr[2] = { 0 };
int no = 0;
int status;
//create the conduit  创建一个管道 并且打开两个文件描述符
//管道中,第一个文件描述符只读,第二个文件描述符只写
no = pipe(fdarr);
if (no == -1)
{
printf("pipe() is failed ! message :%s\n", strerror(errno));
return -1;
}
//创建父子进程
pid_t child = fork();
if (child == -1)
{
printf("system is game over !\n");
return -1;
}
//定义缓存字符串数组
char buf[100] = { 0 };
if (child == 0)
{
/*
管道和文件一样,文件read函数以O_RDONLY方式打开也会阻塞,但是文件数据在本地,读取非常快,感觉不到阻塞,
但是管道以O_RDONLY方式打开,会阻塞进程,read()函数会等待管道另一端写入数据,直到另一端关闭文件描述符
*/
//关闭子进程中的写文件描述符--对于父子进程共享文件描述符,只在单个进程中关闭,只能将文件描述符引用减一,
//因为父子进程中,文件描述符被引用了两次,所以需要在父子进程中分别关闭,才能使文件描述符引用次数减一
close(fdarr[1]);
while (read(fdarr[0], buf, sizeof(buf)) > 0)
{
printf("%s", buf);
//清空缓存区
memset(buf, 0, sizeof(buf));
}
//关闭子进程中读文件描述符
close(fdarr[0]);
} else
{
//关闭父进程中的读描述符
close(fdarr[0]);
//将键盘输入数据写入到管道中
strcpy(buf,"fly on air!\n");
write(fdarr[1], buf, strlen(buf));
//关闭管道写文件描述符
close(fdarr[1]);
//等待子进程结束
wait(&status);
printf("child process is close ! message :%d\n", WEXITSTATUS(status));
}
return 10;
}


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