0

我正在使用 fork,子进程使用 for 循环内的 scanf 从用户读取数据十次。然而,父进程在睡眠 4 秒后向子进程发送 SIGSTOP 信号,并从用户那里读取一个值并打印它。但是,如果用户在子进程中输入了数据但没有为 scanf 按下回车键,则父进程读取但打印写入子进程中的数据。我该如何阻止这种情况发生。

ch=fork();
if(ch==0)
{
    for(i=0;i<10;i++)
    {
        fflush(stdin);
        scanf("%s",buf);
        printf("%d: %s\n",i,buf);
    }
}
else
{
    char buf2[100],cha;
    sleep(4);
    kill(ch,SIGSTOP);
    write(STDOUT_FILENO,"\nchld stopped\n",14);
    memset(stdin,0,sizeof(stdin));
    read(STDIN_FILENO,buf2,2);
    write(STDOUT_FILENO,buf2,2);

    kill(ch,SIGCONT);
    wait(SIGCHLD);
}

因此,例如输出如下所示:

一个

0:一个

b

1:乙

ac(我在这里没有按 Enter 并等待 SIGSTOP)

孩子停止

tr(为父项输入数据并按下回车键)

ac2:tr

C

3:c ...等等

那么输入tr后为什么我的父母显示ac?

4

3 回答 3

2

fflush(stdin)从来都不是正确的做法,尽管很多人都尝试过。fflush仅用于输出。你memset是纯粹的精神错乱。to 的参数wait不应该是一个信号号——它甚至不是正确的类型,所以你应该得到一个你显然忽略的警告。

这些是容易的错误。您正在尝试做的事情存在更深层次的概念问题。

由于您没有修改任何 tty 设置,因此 tty 在程序运行时处于规范模式。这意味着 tty 处理行编辑(退格、Ctrl-U、Ctrl-W 等)并且在行终止之前不会向程序发送任何内容。

当您键入部分行时,该部分行不在标准输入缓冲区中。它在 tty 缓冲区中。它还不属于任何进程。这就是为什么您的父进程可以读取在孩子尝试阅读时部分输入的行。孩子从来没有得到过任何东西。

要清空 tty 缓冲区,这应该有效:关闭规范模式;设置非阻塞模式;读入 a 直到发生错误(当 tty 没有任何东西可以给你时,EAGAIN/EWOULDBLOCK 将在非阻塞模式下发生);重新打开阻塞和规范模式。这个想法是消耗当前可用的任何东西,而无需等待更多。执行各个步骤的代码应该很容易找到。

总的来说,我质疑为用户提供输入信息的机会的界面是否明智,然后自发地中断对该信息的阅读以阅读其他内容。这将导致用户在辅助输入提示下大喊:嘿!我在这里打字!

于 2014-09-15T12:49:46.137 回答
1

好的,我找到了解决方案。

我使用了 tcflush():刷新未传输的输出数据、未读取的输入数据,或两者兼而有之。

tcflush(STDIN_FILENO,TCIFLUSH); 就在父级读取之前的行。

我在这里找到了解决方案... 如何从 UNIX 系统上的 tty 输入队列中刷新未读数据?

于 2014-09-15T13:43:27.970 回答
0

这是因为 read(), write() 函数。当您输入内容而不按回车键时。它将在 stdinput 中,无论在 stdinput 中,它将由 read() 函数存储在您的示例中指定的 buf2 中读取。无论在 buf2 中,它都会通过 write() 发送到 stdoutput。当您注释 read()、write() 函数或仅打印“buf2”时,您可以看到不同之处。

于 2014-09-15T14:01:41.447 回答