咱們已經能夠經過重定向的方式,將子進程的輸出重定向到文件,但咱們想從進程中直接讀取數據,如何使實現。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