如何清除已停止进程的scanf内容?

时间:2014-09-15 12:05:00

标签: c fork flush memset fflush

我正在使用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:a

B'/ P>

1:b

ac(我不按Enter键等待SIGSTOP)

chld停止了

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

ac2:tr

C

3:c ......等等

所以在输入tr后为什么我的父母会显示ac?

3 个答案:

答案 0 :(得分:2)

fflush(stdin)永远不是正确的事情,尽管很多人都尝试过。 fflush仅用于输出。你的memset纯属疯狂。 wait的参数不是一个信号编号 - 它甚至不是正确的类型,所以你应该得到一个你明显忽略的警告。

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

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

键入部分行时,该部分行不在stdin缓冲区中。它在tty缓冲区中。它还不属于任何流程。这就是为什么您的父进程可以读取在孩子尝试阅读时部分键入的行的原因。孩子从来没有得过任何一件事。

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

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

答案 1 :(得分:1)

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

我使用了tcflush():刷新非传输输出数据,非读取输入数据或两者。

tcflush(STDIN_FILENO,TCIFLUSH);就在父母读书之前就行了。

我在这里找到了解决方案...... How can I flush unread data from a tty input queue on a UNIX system?

答案 2 :(得分:0)

这是因为read(),write()函数。输入内容而不按Enter键。它将在stdinput中,无论在stdinput中,它都将通过buf2中的read()函数存储读取,如示例中所指定。无论在buf2中,它都将通过write()发送到stdoutput。您可以在注释read(),write()函数或只是打印&#34; buf2&#34;时看到区别。