Linux系统编程之父子进程通过管道进行通信
管道通信
1.pipe函数
创建管道
int pipe(int pipefd[2]);
返回值成功:0;失败:-1,设置 errno
函数调用成功返回 r/w 两个文件描述符。无需 open,但需手动 close。
规定:
fd[0] → r; fd[1] → w,
就像 0 对应标准输入,1 对应标准输出一样。向管道文件读写数据其实是在读写内核缓冲区。
2.父子进程通过管道通信步骤
建立一个父子进程间的管道通信主要通过以下几步
- 父进程调用 pipe 函数创建管道,得到两个文件描述符 fd[0]、fd[1]指向管道的读端和写端。
- 父进程调用 fork 创建子进程,那么子进程也有两个文件描述符指向同一管道
- 父进程关闭管道读端,子进程关闭管道写端。父进程可以向管道中写入数据,子进程将管道中的数据读出。 由于管道是利用环形队列实现的,数据从写端流入管道,从读端流出,这样就实现了进程间通信。
3.创建一个父子进程通信管道
对父进程关闭读端close(fd[0]);子进程关闭写端close(fd[1]);
实现了父进程往管道里写入,子进程从管道读出
4.利用进程间通信实现ls | wc -l 指令
实现ls | wc -l
.
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<fcntl.h>
int main (int argc ,char * argv[])
{
int fd1,fd2,ret;
int fd[2];
ret = pipe(fd); //创建管道
if (ret == -1)
{
perror("pipe error");
}
pid_t pid = fork();
if (pid == -1)
{
perror("fork error");
exit(1);
}else if (pid > 0) //父进程
{
close(fd[0]);
dup2(fd[1],STDOUT_FILENO);
execlp("ls","ls",NULL);
perror("execlp error");
}else if (pid == 0) //子进程
{
close(fd[1]);
dup2(fd[0],STDIN_FILENO);
execlp("wc","wc","-l",NULL);
}
}
5.兄弟进程间通过管道通信
兄弟进程间通信
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<fcntl.h>
#include<sys/wait.h>
int main (int argc ,char * argv[])
{
int ret,i;
int fd[2];
ret = pipe(fd);
if (ret == -1)
{
perror("pipe error");
}
for (i = 0; i < 2; i++)
{
pid_t pid = fork();
if (pid == -1)
{
perror("fork error");
exit(1);
}
if (pid == 0)
{
break;
}
}
if (i == 0) //哥哥进程
{
//fd1 = open("fc.out",O_RDWR|O_CREAT|O_TRUNC,0777);
close(fd[0]);
dup2(fd[1],STDOUT_FILENO);
execlp("ls","ls",NULL);
perror("execlp error");
}else if (i == 1) //弟弟进程
{
//fd2 = open("fc.out",O_RDWR,0777);
//dup2(STDOUT_FILENO,fd2);
close(fd[1]);
dup2(fd[0],STDIN_FILENO);
execlp("wc","wc","-l",NULL);
//close(fd2);
}else if (i == 2)
{
close(fd[0]);
close(fd[1]);
wait(NULL);
wait(NULL);
}
}