二十六. 管道相关概念
二十七. pipe函数的使用
首先,这里我们写一个pipe.c文件
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
int main(int argc, const char* argv[])
{
int fd[2];
int ret = pipe(fd);
if(ret == -1)
{
perror("pipe error");
exit(1);
}
printf("fd[0] = %d\n", fd[0]);
printf("fd[1] = %d\n", fd[1]);
close(fd[0]);
close(fd[1]);
return 0;
}
运行一下,结果是
[root@VM_0_15_centos 6Day]# ls
a.out eng.txt ipc.c pipe.c write_fifo.c
brother_ipc.c fpathconf.c mmap.c pipe_test.c
english.txt homework parent_child_ipc.c read_fifo.c
[root@VM_0_15_centos 6Day]# vim pipe_test.c
[root@VM_0_15_centos 6Day]# gcc pipe_test.c -o pipe_test
[root@VM_0_15_centos 6Day]# ls
a.out eng.txt ipc.c pipe.c read_fifo.c
brother_ipc.c fpathconf.c mmap.c pipe_test write_fifo.c
english.txt homework parent_child_ipc.c pipe_test.c
[root@VM_0_15_centos 6Day]# ./pipe_test
fd[0] = 3
fd[1] = 4
因为文件描述符0,1,2被占用,所以这里自然而然文件描述符分别是3,4
二十八. 有血缘关系的进程间通信fork的位置
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
int main(int argc, const char* argv[])
{
int fd[2];
int ret = pipe(fd);
if(ret == -1)
{
perror("pipe error");
exit(1);
}
printf("fd[0] = %d\n", fd[0]);
printf("fd[1] = %d\n", fd[1]);
//fork放这里的原因是,子进程中的3号文件描述符与4号文件描述符,同父进程中的文件描述符一样,都指向了这个管道。
pid_t pid = fork();
return 0;
}
二十九. 使用匹配父子进程间通信练习思路
下面这个图很重要,我们大概解释一下
一般情况下,当没有管道的时候,终端连接着STDOUT_FILENO,终端也连接着STDIN_FILENO。当我们要用管道时,将STDOUT_FILENO重定向到内核缓冲区的写端,将STDIN_FILENO重定向到内核缓冲区的读端。
在下图中,我们说父进程的3号文件描述符对应管道的读端, 4号文件描述符对应管道的写端。那么我们做了fork操作后,子进程的3号文件描述符也对应读端,4号文件描述符也对应写端。
这里由于数据只能读一次。
因此父进程读的时候,关闭写端。子进程写的时候,关闭读端。
因此父进程
三十. 父子进程通信——代码实现ps aux grep bash
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
int main(int argc, const char* argv[])
{
// 需要管道
int fd[2];
int ret = pipe(fd);
if(ret == -1)
{
perror("pipe error");
exit(1);
}
// 创建子进程
pid_t pid = fork();
if(pid == -1)
{
perror("fork error");
exit(1);
}
// ps aux | grep bash
// 父进程 ps aux , 写管道, 关闭读端
if(pid > 0)
{
//注意这里父进程写的时候,关闭读端
close(fd[0]);
//文件描述符的重定向
// 数据写到管道,STDOUT_FILENO 指向管道的写端
dup2(fd[1], STDOUT_FILENO);
execlp("ps", "ps", "aux", NULL);
perror("execlp ps");
exit(1);
}
// 子进程 grep bash 从管道中搜索, 读管道, 关闭写端
else if(pid == 0)
{
//注意这里子进程读的时候,关闭写端
close(fd[1]);
dup2(fd[0], STDIN_FILENO);
execlp("grep", "grep", "bash", NULL);
perror("execlp grep");
exit(1);
}
return 0;
}