나는 BSD 소켓 프로그래밍의 맥락에서 걸쳐 실행할 때마다 예와 토론에서는 I를 블로킹에 파일 기술자를 설정하기 위해 권장되는 방법은 / O 모드가 사용하고있는 것 같습니다 O_NONBLOCK
플래그를 위해 fcntl()
예를 들면,
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
저는 10 년 넘게 UNIX에서 네트워크 프로그래밍을 해왔고 항상이 FIONBIO ioctl()
호출을 사용 했습니다.
int opt = 1;
ioctl(fd, FIONBIO, &opt);
그 이유에 대해 정말 많이 생각하지 않았습니다. 그렇게 배웠습니다.
누구든지 둘 중 하나의 가능한 장점에 대한 논평이 있습니까? 나는 이식성 궤적이 다소 다를 것이라고 생각하지만 ioctl_list(2)
개별 ioctl
방법의 측면에 대해 말하지 않는 정도를 알지 못합니다 .
답변
표준화 이전에는 ioctl(
… FIONBIO
… )
및 fcntl(
… O_NDELAY
… )
이 있었지만 이는 시스템간에, 심지어 동일한 시스템 내에서도 일관성없이 작동했습니다. 예를 들어, FIONBIO
소켓 O_NDELAY
에서 작업하고 tty에서 작업 하는 것이 일반적이었으며 파이프, fifo 및 장치와 같은 것에 대한 많은 불일치가있었습니다. 그리고 어떤 종류의 파일 디스크립터를 가지고 있는지 모른다면 두 가지를 모두 설정해야합니다. 그러나 또한 사용 가능한 데이터가없는 비 차단 읽기도 일관성없이 표시되었습니다. OS 및 파일 설명 자의 유형에 따라 읽기는 0, errno EAGAIN의 경우 -1, errno EWOULDBLOCK의 경우 -1을 반환 할 수 있습니다. 오늘도 설정 FIONBIO
이나O_NDELAY
Solaris에서는 데이터가없는 읽기가 tty 또는 파이프에서 0을 반환하거나 소켓에서 errno EAGAIN과 함께 -1을 반환합니다. 그러나 0은 EOF에 대해서도 반환되므로 모호합니다.
POSIX O_NONBLOCK
는 다양한 시스템 및 파일 설명자 유형에서 동작을 표준화 한을 도입하여이 문제를 해결했습니다 . 기존 시스템은 일반적으로 이전 버전과의 호환성을 깨뜨릴 수있는 동작 변경을 피하려고하기 때문에 POSIX는 다른 시스템 중 하나에 대해 특정 동작을 지정하는 대신 새 플래그를 정의했습니다. Linux와 같은 일부 시스템은 3 개를 모두 동일하게 취급하고 EAGAIN 및 EWOULDBLOCK도 동일한 값으로 정의하지만 이전 버전과의 호환성을 위해 다른 레거시 동작을 유지하려는 시스템은 이전 메커니즘을 사용할 때 그렇게 할 수 있습니다.
새 프로그램은 POSIX에 의해 표준화 된대로 fcntl(
… O_NONBLOCK
…를 사용해야합니다 )
.
답변
@Sean이 말했듯 fcntl()
이 거의 표준화되어 있으므로 여러 플랫폼에서 사용할 수 있습니다. 이 ioctl()
함수 fcntl()
는 Unix에서 이전보다 오래 되었지만 전혀 표준화되지 않았습니다. (가) 그건 ioctl()
당신에게 모든 걸쳐 당신을 위해 관련의 플랫폼을했다 다행이지만, 보장 할 수 없습니다. 특히 두 번째 인수에 사용 된 이름은 난해하고 플랫폼간에 신뢰할 수 없습니다. 실제로 파일 설명자가 참조하는 특정 장치 드라이버에 고유 한 경우가 많습니다. ( ioctl()
예를 들어, 20 년 전 PNX (Perq Unix)를 실행하는 ICL Perq에서 실행되는 비트 맵 그래픽 장치에 사용 된 호출은 다른 곳으로 번역되지 않았습니다.)
답변
나는 fcntl()
POSIX 기능 이라고 생각 합니다. ioctl()
표준 UNIX는 어디에 있습니까 ? 다음은 POSIX io 목록입니다 . ioctl()
매우 커널 / 드라이버 / OS에 특화된 것이지만 사용하는 것이 대부분의 유닉스 버전에서 작동한다고 확신합니다. 다른 ioctl()
것들은 특정 OS 또는 커널의 특정 rev에서만 작동 할 수 있습니다.