簡體   English   中英

C程序不能使用管道執行“execlp”中的“more”命令來查看程序的輸出

[英]C program cannot use pipe to execute the "more" command in "execlp" in order to view program's output

提前感謝您的幫助。

我正在嘗試復制 shell 命令ls -1 /usr/include | more的行為。 ls -1 /usr/include | more使用 C 程序。 我寫了這段代碼:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(){
    int page[2];   // page is the name of my pipe
    pipe(page);
    switch (fork()){
    case -1:
        exit(1);
        break;
    case 0:;
        close(page[1]);
        dup2(page[0], 0);
        close(page[0]);
        execlp("more", "more", NULL);
    default:
        close(page[0]);
        dup2(page[1], 1);
        close(page[1]);
        execlp("ls", "ls", "-1", "/usr/include", NULL);
        break;
    }
}

但它只打印一頁( more會做)並導致一些奇怪的行為阻止我的終端(迫使我使用reset將其設置回正常)。

我剛剛意識到父進程和子進程的角色被混淆了。 運行more命令的應該是父級。 由於more是一個交互式命令,終端將作為父級更好地響應它(我猜)。

所以為了解決我的問題,我交換了父母和孩子的角色。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(){
    int page[2];   // page is the name of my pipe
    pipe(page);
    switch (fork()){
    case -1:
        exit(1);
        break;
    case 0:;
        close(page[0]);
        dup2(page[1], 1);
        close(page[1]);
        execlp("ls", "ls", "-1", "/usr/include", NULL);
        break;
    default:
        close(page[1]);
        dup2(page[0], 0);
        close(page[0]);
        execlp("more", "more", NULL);
    }
}

為什么這可以解決問題? (我仍然不明白為什么它有效!)

您的原始代碼在父進程和子進程以及啟動程序的 shell 之間創建了一種競爭條件。 ls進程在more可以從管道中讀取所有數據之前結束,並且由於在您的程序中父進程被ls進程替換,當ls進程結束時(將其所有輸出寫入管道緩沖區后),它退出,並且這樣做會關閉管道並將控制權交還給外殼程序,外殼程序將立即准備好讀取另一個命令。

所以,最初都more與外殼可從同一TTY設備讀取(它是從它的閱讀STDERR描述符,還是連接到您的TTY),然后一旦more ,最終得到了一些輸入,它會嘗試從管道再次讀取(其STDIN ),它將獲得文件結尾(管道已在寫入端關閉,因為ls退出),因此more現在也將退出(不再打印任何輸出)。 more進程和 shell 之間也可能存在競爭,關於哪個(重新)設置 TTY 驅動程序模式以及何時。

程序的另一種實現是讓原始父進程啟動兩個子進程,一個用於more ,一個用於ls ,然后等待兩個進程終止,但這當然需要更多的系統資源。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM