2009-10-20 4 views
8

stdin이 닫히면 실행을 멈추기 위해 순수한 C로 작성된 프로그램이 필요합니다.stdin이 (가) 차단되지 않고 열려 있는지 확인하는 방법?

프로그램 주주기에서 수행되는 무기한 작업이 있으며 블로킹 검사 (예 : getc())를 사용할 수있는 방법이 없습니다 (데이터가 표준 입력에 도달하지 않아도 알 수없는 시간 동안 열렸습니다).

inetd, xinetd 또는 그 유사품에서 호스팅되는 네트워크 데몬을 구현하는 데 위에서 설명한 기능을 사용하려고합니다. 연결이 열린 상태에서 정상적으로 데이터를 내보내고 닫을 때 올바르게 작업해야합니다. 이제 연결 종료 후 프로그램이 중지되지 않으므로 내 프로그램이 호스팅 서비스에 의해 종료됩니다.

fctntl()O_NONBLOCK 플래그를 stdin 설명자에 적용하면 논 블로킹 모드에서 read() 기능을 사용할 수 있습니까? 어떻게 든 select()을 사용해야합니까?

P. 데이터는 가정되지 않지만 표준에 도달 할 수 있습니다. 비 차단 판독 방법은 질문에 대한 대답 일 수 있습니다.

답변

6

select() 정확히 원하는대로 수행하십시오 : 파일 설명자 (파일, 소켓, 뭐든간에)가 조작하지 않는다는 신호를 보냅니다.

#include <stdio.h> 
#include <sys/select.h> 

int is_ready(int fd) { 
    fd_set fdset; 
    struct timeval timeout; 
    int ret; 
    FD_ZERO(&fdset); 
    FD_SET(fd, &fdset); 
    timeout.tv_sec = 0; 
    timeout.tv_usec = 1; 
    //int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, 
    struct timeval *timeout); 
    return select(fd+1, &fdset, NULL, NULL, &timeout) == 1 ? 1 : 0; 
} 
이제 파일 기술자 비우하기 위해 예를 들어, 사용하기 전에 파일 기술자를 확인할 수 있습니다

: 파일 기술자를 얻을 수 fileno (표준 입력)를 사용, 귀하의 경우에는

void empty_fd(int fd) { 
    char buffer[1024]; 
    while (is_ready(fd)) { 
     read(fd, buffer, sizeof(buffer)); 
    } 
} 

을 표준 입력의 : O_NONBLOCK 플래그 fctntl은() 하시다 표준 입력 기술자에 적용되는 경우

if (is_ready(fileno(stdin))) { 
    /* read stuff from stdin will not block */ 
} 
+0

'poll' 역시 정확히 OP가 원하는 것이며, 그 인터페이스는 작고 고정 된 파일 디스크립터 집합을 다룰 때'select'보다 약간 더 쉽습니다. – ephemient

0

feof(stdin)의 문제점은 무엇입니까?

+0

모든 데이터를 읽지 않으면 작동하지 않습니다. 작업을 차단하지 않고 모든 데이터 (예 : 휴지통)를 읽으려면 어떻게해야합니까? – Basilevs

+0

오픈 표준에 EOF를 삽입 할 수 있습니다 (예 : Linux의 경우 Ctrl-D 사용). 표준이 닫혀 있다는 것을 의미하지는 않습니다. –

1

stdin에서 O_NONBLOCK을 설정할 수 있는지 여부는 확실하지 않지만 select() 또는 poll()은 확실히 완료됩니다.

+0

예, stdin에 O_NONBLOCK을 설정할 수 있습니다. stdin이 다른 프로그램에서 파이프되면, 그 프로그램은 아웃 바운드 파일 디스크립터를 비 블로킹으로 처리하지 못할 수 있습니다. – ephemient

0

예, select (시간 제한 없음)을 사용할 수 있습니다. 파일 디스크립터를 비 블로킹으로 설정할 필요는 없습니다. select에서 파일 디스크립터가 읽을 수 있다고 알려주면 read은 확실히 차단되지 않습니다.

파일 설 명자 0을 가끔 select으로 폴링하고 읽을 수있는 경우 read입니다. read이 0을 반환하면 닫힌 것입니다.

2

궁금하다 uld는 non-blocking 모드에서 read() 함수를 사용할 수 있습니까?

O_NONBLOCK으로 stdin을 실행하면 select보다 이점이 있습니다. Select는 데이터가 있지만 얼마가 있는지 말합니다. 대기열의 양에 관계없이 사용 가능한 모든 데이터를 가져오고 차단하지 않을 때가 있습니다. 각 캐릭터에 대해 select를 실행하는 것은 많은 바쁜 작업처럼 보입니다 ... O_NONBLOCK은 나를 위해 작동하지 않았습니다. 대부분의 tty 드라이버에는 노출되지 않는 내부 플래그입니다.

ioctl (..., FIONBIO)을 확인하십시오. 그 일을 끝내는 것 같습니다.