咱们已经能够经过重定向的方式,将子进程的输出重定向到文件,但咱们想从进程中直接读取数据,如何使实现。python
咱们曾经用一个命令来链接进程,那就是管道:git
python fake_rss.py | grep 'naruto'
能够用管道把一个进程的输出链接到另外一个进程的输入。 管道两侧的命令是父子关系。github
若是想在c代码中,而不是命令行中实现管道链接,该怎么作呢。数组
咱们要作如下两件事:浏览器
咱们要在进程中建立两条新的流,用于管道的读取与写入。函数
# | 数据流 |
---|---|
0 | stdin |
1 | stdout |
2 | stderr |
3 | 管道读取端 |
4 | 管道写入端 |
pipe()
函数创建管道 由于子进程要把数据发送到父进程里,因此要用管道链接子进程的标准输入和父进程的标准输出。 咱们说过,每当打开数据流时,它都会加入描述符表。pipe()
函数也是如此,它建立两条相连的数据流,并把它们加入描述符表中。 这样你只要从一条数据流中写入数据,就能从另外一条数据流中读取int fd[2]; if (pipe(fd) == -1) { error("Can't create pipe"); }
if (pid == 0) { dup2(fd[1], 1); close(fd[0]); execlp("python", "python", "./fake_rss.py", NULL);
} 2. 父进程的操做
c dup2(fd[0], 0); close(fd[1]); char line[255]; while (fgets(line, sizeof(line) / sizeof(char), stdin)) { if (line[strlen(line) - 1] == '\n') line[strlen(line) - 1] = 0; printf("Got url :%s\n", line);url
pid_t pid2 = fork(); if (pid2 == 0) { open_url(line); }
} ``` 父进程要作的是: 1. 将标准输入stdin重定向到*fd[0]*的数据流。 2. 用一个while循环从stdin读入数据,判断条件为读入的结果(当执行脚本结束时会返回EOF,fgets()返回0,循环结束)。 3. 再fork()一次,用于建立多个子进程打开多个url。命令行
有名管道是基于文件的管道,也叫作FIFO(First In First Out)文件。 由于基于文件的管道有名字,因此两个进程只要知道管道的名字就能用它来通讯,即便它们不是父子进程。 使用系统调用mkfifo()能够建立有名管道。code