2014-09-15 10 views
0

포크를 사용하고 하위 프로세스가 for 루프 내부의 scanf를 사용하여 사용자로부터 데이터를 10 번 읽습니다. 그러나 부모 프로세스는 4 초간 휴면 후 SIGSTOP 신호를 자식에게 보내고 사용자로부터 값을 읽어서 인쇄합니다. 그러나 사용자가 데이터를 입력했지만 누르지 않은 경우 하위 프로세스에서 scanf에 대해 enter를 입력하면 상위 프로세스는 하위 프로세스에서 작성된 데이터를 읽지 만 인쇄합니다. 이 일이 일어나지 않게하려면 어떻게해야합니까? 중지 된 프로세스의 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

1 : B-에게

교류 (내가 그나마 Enter 키를 누릅니다 여기 그리고 SIGSTOP 기다림)

,

CHLD는

TR 정지 (상위에 입력 데이터를 입력 누름)

AC2 : TR

C

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가 행 편집 (백 스페이스, Ctrl-U, Ctrl-W 등)을 처리하고 행이 종료 될 때까지 프로그램에 아무 것도 보내지 않음을 의미합니다.

부분 행을 입력하면 해당 부분 행이 표준 버퍼에 없습니다. 그것은 tty 버퍼에 있습니다. 아직 어떤 프로세스에도 속하지 않습니다. 그래서 부모 프로세스가 자식이 읽으려고하는 동안 부분적으로 입력 된 행을 읽을 수 있습니다. 그 아이는 그 어떤 것도 갖지 못했습니다.

tty 버퍼를 비우려면 다음이 필요합니다. 표준 모드를 ​​끕니다. 비 차단 모드로 설정; 오류가 발생할 때까지 (EAGAIN/EWOULDBLOCK은 tty가 당신에게 줄 아무것도 남겨놓지 않았을 때 비 차단 모드에서 일어날 때까지) 읽습니다. 차단 및 표준 모드를 ​​다시 시작합니다. 아이디어는 더 기다리지 않고 현재 사용할 수있는 것을 소비하는 것입니다. 개별 단계를 수행하는 코드는 쉽게 찾을 수 있어야합니다.

일반적으로 나는 사용자에게 정보를 입력 할 수있는 기회를 제공하는 인터페이스의 지혜에 의문을 제기합니다. 그런 다음 정보의 읽기를 자발적으로 중단하여 다른 것을 읽습니다. 사용자가 보조 입력 프롬프트에서 소리 치게됩니다. HEY! 나는 여기에 타자를 치고있어!

+0

좋아요.하지만 여전히 tty 버퍼를 지우는 방법을 알려주시겠습니까? –

0

이 때문에 읽기입니다(),() 함수를 작성합니다. Enter 키를 누르지 않고 입력 할 때. 그것은 stdinput에있을 것이고, stdinput에서 무엇이든간에, 여러분의 예제에서 지정된대로 buf2의 read() 함수 스토어에 의해 읽혀질 것이다. 그리고 buf2에서 무엇이든, 그것은 stdoutput에 write()에 의해 보내질 것이다. read(), write() 함수를 주석 처리하거나 "buf2"만 출력하면 차이점을 알 수 있습니다.