子进程通过管道发送一个数字,然后等待

标签 c pipe sleep

我正在尝试生成两个通过管道连接的子进程。 child 1 应该通过管道向 child 2 发送一个数字, child 2 应该打印它。我设法做到了这一点,但是当我尝试循环执行此操作时,子 1 每次在发送另一个号码之前等待 1 秒,它不会发送任何内容。
我做错了什么?

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <windows.h>

int main(int argc, char *argv[]) {
    int fd[2];
    pipe(fd);
    pid_t pid1 = fork();
    if (pid1) {
        pid_t pid2 = fork();
        if (pid2) { //parent
            // do stuff as parent
        } else { //child 2
            close(fd[1]);
            char stringNumberReceived[10];
            while (1) {
                read(fd[0], stringNumberReceived, sizeof (stringNumberReceived));
                printf("number received: %s\n", stringNumberReceived);
            }
        }
    } else {//child 1
        close(fd[0]);
        int num;
        char stringnumber [10];
        while (1) {
            num = rand();
            snprintf(stringnumber, 10, "%d", num);
            printf("attempting to sent: %s\n", stringnumber);
            write(fd[1], stringnumber, strlen(stringnumber) + 1);
            Sleep(1000);
        }
    }
}

最佳答案

这是代码的稍微修改版本:

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

enum { MAX_COUNT = 20 };

int main(void)
{
    int fd[2];
    pipe(fd);
    pid_t pid1 = fork();
    if (pid1)
    {
        pid_t pid2 = fork();
        if (pid2)   // parent
        {
            printf("Child 1: %d; child 2: %d\n", (int)pid1, (int)pid2);
            close(fd[0]);   // Let the child detect EOF!
            close(fd[1]);   // Let the child detect EOF!
            int corpse;
            int status;
            while ((corpse = wait(&status)) > 0)
                printf("PID %d exited with status 0x%.4X\n", corpse, status);
        }
        else     // child 2
        {
            close(fd[1]);
            char stringNumberReceived[10];
            int nbytes;
            while ((nbytes = read(fd[0], stringNumberReceived, sizeof(stringNumberReceived))) > 0)
                printf("number received: %.*s\n", nbytes, stringNumberReceived);
            printf("Child 2: EOF or ERR\n");
        }
    }
    else    // child 1
    {
        close(fd[0]);
        int num;
        char stringnumber[10];
        for (int counter = 0; counter < MAX_COUNT; counter++)
        {
            num = rand();
            snprintf(stringnumber, sizeof(stringnumber), "%d", num);
            printf("attempting to send: [%s] (len %zu)\n", stringnumber, strlen(stringnumber));
            write(fd[1], stringnumber, strlen(stringnumber) + 1);
            sleep(1);
        }
    }
    return 0;
}

什么改变了?各种各样的事情。您可以忽略牙套位置的变化;这纯粹是装饰性的。

  1. 父代码已实现。
  2. 父进程报告子进程 ID。
  3. 父级关闭管道 - 它既不读取也不写入。
  4. 父级等待子级死亡,并在子级死亡时报告状态。
  5. Child 记录它读取了多少字节,并确保它打印的字节数不超过该值。
  6. 当管道上出现错误或 EOF(读取 0 字节)时,它会终止循环并在退出前进行报告。
  7. 其他 child 在退出前执行固定次数的循环(如图所示 20 次)。
  8. 如果随机数生成器生成 10 位以上的数字,则可能会遇到数组边界问题。我得到的最大长度是 9,这是安全的。
  9. 生成子进程可以/应该在完成时进行报告。

在这些更改中,我怀疑关闭父级中的管道可能是关键。

示例输出(在 Unix 机器上):

$ pp43
attempting to send: [16807] (len 5)
Child 1: 69198; child 2: 69199
number received: 16807
attempting to send: [282475249] (len 9)
number received: 282475249
attempting to send: [162265007] (len 9)
number received: 162265007
attempting to send: [984943658] (len 9)
number received: 984943658
attempting to send: [114410893] (len 9)
number received: 114410893
attempting to send: [470211272] (len 9)
number received: 470211272
attempting to send: [101027544] (len 9)
number received: 101027544
attempting to send: [145785087] (len 9)
number received: 145785087
attempting to send: [145877792] (len 9)
number received: 145877792
attempting to send: [200723770] (len 9)
number received: 200723770
attempting to send: [823564440] (len 9)
number received: 823564440
attempting to send: [111543816] (len 9)
number received: 111543816
attempting to send: [178448449] (len 9)
number received: 178448449
attempting to send: [74243042] (len 8)
number received: 74243042
attempting to send: [114807987] (len 9)
number received: 114807987
attempting to send: [113752250] (len 9)
number received: 113752250
attempting to send: [144128232] (len 9)
number received: 144128232
attempting to send: [16531729] (len 8)
number received: 16531729
attempting to send: [823378840] (len 9)
number received: 823378840
attempting to send: [143542612] (len 9)
number received: 143542612
Child 2: EOF or ERR
PID 69198 exited with status 0x0000
PID 69199 exited with status 0x0000
$

关于子进程通过管道发送一个数字,然后等待,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43120883/

相关文章:

python - 使用 python 列表作为使用 stdin 作为输入的 linux 命令的输入

python - 将 fork 的 python 进程的输出重定向到管道

java - 如何使用 sleep 方法重复声音

c - 矩阵乘法错误 : Segmentation fault (core dumped)

Python 和子进程输入管道

php - php 中 sleep() 函数的替代方案

java - Java 中的 Thread.yield() 和 Thread.sleep(0) 有什么区别?

c - 为什么在捕获 SIGALRM 后 recvfrom() 仍然阻塞?

c - 写入后从磁盘读取而不是缓存

C 创建txt文件并附加当前日期和时间作为名称