【问题标题】:PingPong by 1 pipe and 1 signal: what is scanf waiting for?PingPong 由 1 个管道和 1 个信号:scanf 在等待什么?
【发布时间】:2019-05-02 13:13:12
【问题描述】:

我在 C 上通过 1 个信号和 1 个管道编写了 PingPong,所以我需要将 pid1 发送到 son2pid2son1,其中 pid1pid2son1son2 的 pid。

但我看到了这张照片:

Waiting..

PID: 4021

Waiting..

我有这个代码:

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>

int pidN;
int pid = -1;
int fd[2];
int max;

void SIGUSR1_hdl(int sig)
{
    // Set pid
    if (pid == -1) {
        printf("Waiting..\n");
        fflush(stdout);
        scanf("%d", &pid);
        printf("PID: %d\n", pid);
        fflush(stdout);
        kill(pid, SIGUSR1);
        signal(SIGUSR1, SIGUSR1_hdl);
        return;
    }
    // Read x
    ..
    }

int main(int argc, const char **argv)
{
    signal(SIGUSR1, SIGUSR1_hdl);
    sscanf(argv[1], "%d", &max);
    pipe(fd);
    dup2(fd[0], STDIN_FILENO);
    close(fd[0]);

    int pid1;
    if (!(pid1 = fork())) {
        pidN = 1;
        for (;;) pause();
    }

    int pid2;
    if (!(pid2 = fork())) {
        pidN = 2;
        for (;;) pause();
    }

    kill(pid1, SIGUSR1);
    dprintf(fd[1], "%d\n%d\n%d\n", pid2, pid1, 1);
    close(fd[1]);
    wait(NULL);
    wait(NULL);

    return 0;
}

它在 SIGUSR1_hdl 的 son2 中的 scanf 之前挂出。我究竟做错了什么? 我不能通过叉子继承pids。我只能通过我的频道 (fd) 发送。

【问题讨论】:

  • fflush()scanf()printf() 不保证是异步信号保存。不应从信号处理程序中调用它们。

标签: c pipe signals fork


【解决方案1】:

主要问题(除了您使用的信号不安全函数)是当stdin 连接到非终端输入时,它完全缓冲。这意味着当您尝试从stdinscanf 所做的事情)读取数据时,它将尝试尽可能多地填充缓冲区。

这意味着单个子进程将读取所有您写入管道的数据,而不会为其他子进程留下任何数据,这当然会导致scanf 无限阻塞。

您要么需要使用两个管道,一个用于每个子进程,要么需要使用其他方式在进程之间进行同步。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2020-06-25
  • 2011-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-01
  • 2020-09-24
  • 2022-01-20
相关资源
最近更新 更多