簡體   English   中英

沒有從管道中獲得所有管線

[英]Not getting all the lines from a pipe

我正在做一個作業,需要一些流程(父母和孩子)進行溝通。 父級將文件路徑發送給子級,並且子級必須在子級上運行linux file (/ usr / bin / file),並將輸出返回給父級。

目前,我仍在努力讓一個孩子上班,所以現在,我假設有一個孩子。

我打算將多個文件路徑發送給每個孩子(一批文件),然后讀取file的輸出。

問題:

我使用循環來write一些文件路徑,但是當我read孩子的輸出管道時,並沒有得到我應該得到的所有輸出。

編碼:

#define Read            0
#define Write           1
#define ParentRead      read_pipe[0]
#define ParentWrite     write_pipe[1]
#define ChildRead       write_pipe[0]
#define ChildWrite      read_pipe[1]
#define PIPE_BUF_LEN    4096

using namespace std;
int main()
{
    /** Pipe for reading for subprocess */
    int read_pipe[2];
    /** Pipe for writing to subprocess */
    int write_pipe[2];
    char buffer[PIPE_BUF_LEN] = "";
    if (pipe(read_pipe) == 0 && pipe(write_pipe) == 0)
    {
        pid_t pid = fork();
        if (pid == -1)
        {
            fprintf(stderr, "Fork failure");
            exit(EXIT_FAILURE);
        }
        else if (pid == 0) //Child process
        {
            close(ParentRead);
            close(ParentWrite);
            dup2 (ChildRead, STDIN_FILENO); /*redirect ChildRead to stdin*/
            dup2 (ChildWrite, STDOUT_FILENO); /*redirect stdout to ChildWrite*/
            char* paramArgs[]={"/usr/bin/file","-n","-f-",NULL};
            execv("/usr/bin/file",paramArgs);
            exit(EXIT_FAILURE);
        }
        else { //Parent process
            close(ChildRead);
            close(ChildWrite);

            for (int i=0; i < 3 ;i++)
            {
                /*write to processes which are ready for writing: */
                fd_set rfds;
                int retval;
                FD_ZERO(&rfds);
                FD_SET(ParentWrite, &rfds);
                retval = select(10, NULL, &rfds, NULL, NULL);
                if (retval == -1)
                {
                    perror("select()");
                }
                else if (retval)
                {
                    write(ParentWrite, "file1\nfile2\n", 12);
                }
                /*read from processes which are ready for reading*/
                FD_ZERO(&rfds);
                FD_SET(ParentRead, &rfds);
                retval = select(10, &rfds, NULL, NULL, NULL);
                if (retval == -1)
                {
                    perror("select()");
                }
                else if (retval)
                {
                    read(ParentRead, buffer, PIPE_BUF_LEN);
                    cout << buffer;
                }
            }
        }
    }
    exit(EXIT_SUCCESS);
}

在這種情況下,我嘗試在3次迭代的循環中在“ file1 \\ nfile2 \\ n”上運行file (注意使用了-n -f-標志),期望得到六行,但僅得到三行:

file1:錯誤:無法打開`file1'(沒有這樣的文件或目錄)

file2:錯誤:無法打開`file2'(沒有這樣的文件或目錄)

file1:錯誤:無法打開`file1'(沒有這樣的文件或目錄)

當我不將孩子的輸出重定向到管道(將其寫入std_out)時,我確實得到了全部六行。

任何幫助將不勝感激。

調度程序。 您處於一個循環中,要求孩子(即pgm file )三遍地查找兩個文件。 您只能在父級的每個循環中讀取一次。

  • 如果子進程已調度且不間斷,則它將執行第一個文件查找,寫入管道,執行第二次查找,寫入管道。 父母安排好了,您一次閱讀了孩子的全部輸出。 你是金色的(但很幸運)。
  • 子進程已安排好,進行第一次查找和管道寫入並被中斷。 父級讀取一個輸出。 子級被重新安排並進行第二次查找並寫入管道。 父級讀取一個輸出。 因為您只讀取3次,所以最終只能讀取6個輸出中的3個。
  • 上面的變化。 也許您會讀到1個輸出,然后讀3個,然后讀1個。您只是不知道。

請注意,至少每次讀取都獲得完整的子級輸出的原因是,如果管道寫操作的長度小於PIPE_BUF,則保證它們是原子的。 如果在套接字上使用這種例行程序,則每次讀取時最終可能會得到消息的一部分。

解決方案:您必須循環閱讀,直到獲得所需的字節數(或完整消息)為止。 在這種情況下,我假設file的輸出始終是一個以換行符結尾的字符串。 但是您每次通過循環都要求兩個file輸出。 因此,請閱讀直到滿足該條件為止,即直到您閱讀了兩個完整的字符串。

暫無
暫無

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

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