簡體   English   中英

無限循環中子級的read()stdout

[英]read() stdout from child in infinite loop

我正在分叉一個孩子,它將運行無限循環並執行某些操作。 當孩子處於“就緒”狀態時,將使用printf將文本打印到標准輸出。 我正在用管道重定向孩子的標准輸出,以便父母可以看到它。 當此文本打印出來時,我希望父母不受阻礙。

問題似乎是,即使在printf()調用之后,read()調用也將保持阻塞狀態。

這是我正在使用的一些示例代碼:

父母:

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

int main()
{
    int fd[2];
    pipe(fd);
    char buffer[256];

    switch(fork())
    {
        case -1:
            printf("fork failed\n");
            _exit(1);
        case 0:
            printf("Starting progtest...\n");
            close(fd[0]);
            dup2(fd[1], STDOUT_FILENO);
            close(fd[1]);
            execl("progtest", "progtest", NULL);

            perror("exec failed");
            _exit(1);
    }

    close(fd[1]);
    read(fd[0], &buffer, sizeof(buffer));
    close(fd[0]);

    printf("buffer: %s\n", buffer);

}

兒童:

#include <stdio.h>

int main()
{
    printf("ready\n");
    while(1)
    {
        // stuff happens here
    }

    return 0;
}

我很確定管道設置正確。 如果刪除無限循環,則父級將取消阻止並打印“就緒”。

孩子仍在運行時,有什么方法可以使用read()? 我通過使用管道來解決這個問題嗎? 我需要用兩個不同的狀態消息執行兩次。

看來您正在嘗試執行進程間通信(IPC)。 沒有具有讀/寫功能的一對一通信同步,父級或子級可以一次向文件描述符中寫入任意數量的文件,並且由於它們是異步運行的,因此必須確保已准備好進行處理。

通常,這是通過發送帶有固定大小的每個消息的標頭來完成的,其中包含有效載荷的長度。 例如:

協議頭

#include <stdint.h>

struct Message
{
  uint8_t length; // assuming a maximum message length of 255 bytes, adjust as needed.
};

您可以在此處定義其他內容,通常最好包括版本,序列ID等。重要的是,如果您通過網絡進行通信,則此標頭的大小在所有硬件實現中都是絕對的,因此使用需要stdint定義以確保體系結構之間的兼容性。 如果也跨架構工作,則確保字節序是一致的也是一個好主意。

發送信息

const char data[] = "example";

// create a buffer large enough to pack the header and data into it
const uint8_t len = strlen(data) + 1;
char buffer[sizeof(struct Message) + len];

// populate the header
struct Message *m = (struct Message *)buffer;
m->length = len;

// copy in the payload after the header
memcpy(buffer + sizeof(struct Message), data, len);

// write the packed buffer
write(fd, buffer, sizeof(struct Message) + len);

閱讀訊息

struct Message m;
if (read(fd, &m, sizeof(struct Message)) != sizeof(struct Message))
{
  fprintf(stderr, "Failed to read the header\n");
  exit(1);
}

// If required perform validation on the header here

ssize_t offset = 0;
char data[m.length];
while(offset < m.length)
{
  ssize_t r = read(fd, data + offset, m.length - offset);
  if (r < 0)
  {
    fprintf(stderr, "Read of message body failed\n");
    exit(1);
  }

  if (r == 0)
  {
    fprintf(stderr, "The sender closed the connection\n");
    exit(1);
  }

  offset += r;
}

printf("Message Length: %u, Message Data: %s\n", m.length, data);

需要使用while循環,因為如果發送方超出了寫緩沖區,並且現在阻止等待寫其余部分,則數據可能已拆分為多個塊。 標頭也可以拆分成多個塊,理想情況下也應該使用相同的技術讀取,但是為了簡潔起見,我省略了它。

暫無
暫無

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

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