簡體   English   中英

將 exec 輸出重定向到緩沖區或文件

[英]Redirecting exec output to a buffer or file

我正在編寫一個 C 程序,其中我fork()exec()wait() 我想將我執行的程序的輸出寫入文件或緩沖區。

例如,如果我 exec ls我想將file1 file2 etc寫入緩沖區/文件。 我認為沒有辦法讀取標准輸出,這是否意味着我必須使用管道? 這里有我找不到的一般程序嗎?

將輸出發送到另一個文件(我省略了錯誤檢查以關注重要細節):

if (fork() == 0)
{
    // child
    int fd = open(file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);

    dup2(fd, 1);   // make stdout go to file
    dup2(fd, 2);   // make stderr go to file - you may choose to not do this
                   // or perhaps send stderr to another file

    close(fd);     // fd no longer needed - the dup'ed handles are sufficient

    exec(...);
}

用於將輸出發送到管道,以便您可以將輸出讀入緩沖區:

int pipefd[2];
pipe(pipefd);

if (fork() == 0)
{
    close(pipefd[0]);    // close reading end in the child

    dup2(pipefd[1], 1);  // send stdout to the pipe
    dup2(pipefd[1], 2);  // send stderr to the pipe

    close(pipefd[1]);    // this descriptor is no longer needed

    exec(...);
}
else
{
    // parent

    char buffer[1024];

    close(pipefd[1]);  // close the write end of the pipe in the parent

    while (read(pipefd[0], buffer, sizeof(buffer)) != 0)
    {
    }
}

你需要准確地決定你想做什么——最好解釋得更清楚一點。

選項 1:文件

如果您知道要將執行命令的輸出轉到哪個文件,則:

  1. 確保父母和孩子就名字達成一致(父母在分叉之前決定名字)。
  2. 父叉 - 你有兩個進程。
  3. Child 重新組織事物,以便文件描述符 1(標准輸出)進入文件。
  4. 通常,您可以不考慮標准誤差; 您可以從 /dev/null 重定向標准輸入。
  5. Child 然后執行相關命令; 所述命令運行並且任何標准輸出都進入文件(這是基本的 shell I/O 重定向)。
  6. 然后執行的進程終止。
  7. 同時,父進程可以采用以下兩種主要策略之一:
    • 打開文件進行閱讀,並繼續閱讀,直到達到 EOF。 然后它需要仔細檢查孩子是否死了(所以不會有更多的數據要讀取),或者等待孩子的更多輸入。
    • 等孩子死了再打開文件閱讀。
    • 第一個的好處是父母可以在孩子跑步的同時做一些工作; 第二種方法的優點是您不必玩弄 I/O 系統(反復讀取 EOF)。

選項 2:管道

如果您希望父級讀取子級的輸出,請安排子級將其輸出通過管道傳回父級。

  1. 使用 popen() 以簡單的方式做到這一點。 它將運行該進程並將輸出發送到您的父進程。 請注意,當子進程生成輸出時,父進程必須處於活動狀態,因為管道的緩沖區大小很小(通常為 4-5 KB),如果子進程生成的數據多於父進程未讀取的數據,則子進程將阻塞,直到家長閱讀。 如果父母正在等待孩子死去,那么你就會陷入僵局。
  2. 使用 pipe() 等很難做到這一點。 Parent 調用 pipe(),然后調用 fork。 子進程對管道進行排序,以便管道的寫入端是其標准輸出,並確保與管道相關的所有其他文件描述符都已關閉。 這很可能使用 dup2() 系統調用。 然后它執行所需的過程,將其標准輸出發送到管道中。
  3. 同時,父級也關閉了不需要的管道末端,然后開始讀取。 當它在管道上獲得 EOF 時,它知道孩子已經完成並關閉了管道; 它也可以關閉管道的末端。

由於您看起來將在 linux/cygwin 環境中使用它,因此您想使用popen 這就像打開一個文件,只有你會得到正在執行的程序stdout ,所以你可以使用你正常的fscanffread等。

fork 后,使用dup2(2)將文件的 FD 復制到 stdout 的 FD 中,然后執行。

您還可以使用 linux sh命令並向其傳遞包含重定向的命令:

string cmd = "/bin/ls > " + filepath;

execl("/bin/sh", "sh", "-c", cmd.c_str(), 0);

暫無
暫無

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

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