2014-09-15 3 views
0

Я использую fork, и дочерний процесс считывает данные десять раз от пользователя, используя scanf внутри цикла for. Однако родительский процесс отправляет сигнал SIGSTOP ребенку после 4 секунд сна и считывает значение от пользователя и печатает его. Но если пользователь ввел данные, но не нажал enter для scanf в дочернем процессе, родительский процесс читает, но печатает данные, записанные в дочернем процессе. Как я могу остановить это от счастья.Как очистить содержимое 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: а

б

1: б

переменного тока (я не нажмите клавишу ВВОД здесь и дождаться SIGSTOP)

CHLD остановил

Tr (Введенные данные для родителей и нажать ввод)

ac2: тр

с

3: с ... и так далее

Таким образом, после ввод tr, почему мой родительский дисплей ac?

ответ

1

Хорошо, я нашел решение.

Использовал tcflush(): сбросить выходные данные, не читаемые входные данные или и то, и другое.

tcflush (STDIN_FILENO, TCIFLUSH); строка перед чтением в родительском файле.

Я нашел решение здесь ... How can I flush unread data from a tty input queue on a UNIX system?

2

fflush(stdin) никогда не подойдет, хотя многие люди его попробовали. fflush предназначен только для вывода. Ваш memset - это чистое безумие. Аргумент wait не должен содержать номер сигнала - это даже не правильный тип, поэтому у вас должно быть предупреждение, которое вы, по-видимому, игнорируете.

Это простые ошибки. Существуют более глубокие концептуальные проблемы с тем, что вы пытаетесь сделать.

Поскольку вы не изменяли настройки tty, tty находится в каноническом режиме, пока ваша программа запущена. Это означает, что tty обрабатывает редактирование строк (backspace, Ctrl-U, Ctrl-W и т. Д.) И не передает ничего в программу до тех пор, пока линия не будет прервана.

Когда вы набрали частичную линию, эта частичная линия не находится в буфере stdin. Он находится в буфере tty. Это еще не относится к процессу. Вот почему ваш родительский процесс может прочитать строку, которая была частично напечатана, когда ребенок пытался прочитать. Ребенок так и не получил этого.

Чтобы освободить буфер tty, это должно работать: выключите канонический режим; установить неблокирующий режим; прочитайте в до тех пор, пока не произойдет ошибка (EAGAIN/EWOULDBLOCK произойдет в неблокирующем режиме, когда tty ничего не оставит вам); включить блокировку и канонический режим. Идея состоит в том, чтобы потреблять все, что доступно в настоящее время, не дожидаясь большего. Код для выполнения отдельных шагов должен быть легко найти.

В целом, я задаю вопрос о мудрости интерфейса, который предлагает пользователю возможность вводить информацию, а затем спонтанно прерывает чтение этой информации, чтобы читать что-то еще. Это заставит пользователей кричать во вспомогательном приглашении ввода: HEY! Я ТИП ЗДЕСЬ!

+0

Хорошо, но все же вы можете сказать мне, как очистить буфер tty? –

0

Это из-за чтения(), писать() функцию. Когда вы вводите что-то, не нажимая enter. Он будет в stdinput, независимо от stdinput, он будет считываться с помощью функции read() в buf2, как указано в вашем примере. И что бы ни было в buf2, он отправит stdoutput командой write(). Вы можете видеть разницу, когда вы комментируете функцию read(), write() или просто печатаете «buf2».

Смежные вопросы