NAME
ioctl - 장치 제어하기
SYNOPSIS
#include <sys/ioctl.h>
int ioctl(int fd, unsigned long request, ...);
DESCRIPTION
ioctl()
시스템 호출은 특수 파일 기반 장치의 매개변수들을 조작한다. 특히 문자 특수 파일(가령 터미널)의 여러 동작 특성들을 ioctl()
요청으로 제어할 수 있다. fd
인자는 열린 파일 디스크립터여야 한다.
두 번째 인자는 장치에 따라 달라지는 요청 코드다. 세 번째 인자는 타입 없는 메모리 포인터다. 전통적으로 (void *
가 C에서 유효하기 전부터) char *argp
였으므로 여기서도 그렇게 부를 것이다.
ioctl()
의 request
값에는 인자가 입력 매개변수인지 아니면 출력 매개변수인지, 그리고 argp
인자의 바이트 단위 크기는 얼마인지가 담겨 있다. ioctl()
의 request
를 명세하는 데 쓰는 매크로와 정의들이 <sys/ioctl.h>
파일에 있다. NOTES 참고.
RETURN VALUE
일반적으로 성공 시 0을 반환한다. 몇몇 ioctl()
요청은 반환 값을 출력 매개변수로 사용하여 성공 시 음수 아닌 값을 반환한다. 오류 시 -1을 반환하며 오류를 나타내도록 errno
를 설정한다.
ERRORS
EBADF
fd
가 유효한 파일 디스크립터가 아니다.EFAULT
argp
가 접근 불가능한 메모리 영역을 가리키고 있다.EINVAL
request
나argp
가 유효하지 않다.ENOTTY
fd
가 문자 특수 파일에 연계돼 있지 않다.ENOTTY
- 지정한 요청이 파일 디스크립터
fd
가 가리키는 종류의 객체에 적용되지 않는다.
CONFORMING TO
어떤 단일 표준이 없다. 장치 드라이버에 따라서 ioctl()
의 인자와 반환 값, 동작 방식이 달라진다. (이 호출은 유닉스의 스트림 I/O 모델에 깔끔하게 들어맞지 않는 동작들을 위한 잡동사니 상자 역할을 한다.)
AT&T UNIX 버전 7에서 ioctl()
시스템 호출이 등장했다.
NOTES
이 호출을 이용하려면 열린 파일 디스크립터가 있어야 한다. open(2) 호출에 원치 않는 부대 효과가 있는 경우가 많은데, 리눅스에선 O_NONBLOCK
플래그를 줘서 피할 수 있다.
ioctl 값의 구조
ioctl 명령 값은 32비트 정수다. 원칙적으로 그 상수들은 완전히 임의적이지만 사람들이 그 안에 어떤 구조를 만들어 넣으려고 했다.
리눅스 옛날 버전에서는 대부분 16비트인 상수들 중 마지막 바이트가 일련 번호이고 그 앞의 바이트가 (또는 바이트들이) 드라이버를 나타내는 타입 값이다. 때로는 주 번호를 써서, HDIO_*
ioctl에는 0x03을 쓰고 LP*
ioctl에는 0x06을 썼다. 또 때로는 ASCII 문자 한두 개를 썼다. 예를 들어 TCGETS
의 값은 0x00005401인데 0x54 = 'T'가 터미널 드라이버를 나타내며, CYGETTIMEOUT
의 값은 0x00435906인데 0x43 0x59 = 'C' 'Y'가 Cyclades 드라이버를 나타낸다.
이후 (0.98p5) 그 수에 좀 더 많은 정보가 들어갔다. 방향 비트 2개(00: 없음, 01: 쓰기, 10: 읽기, 11: 읽기/쓰기)와 크기 비트 14개(인자의 크기를 나타냄)에 이어 8비트 타입 값(ioctl들을 용도 및 드라이버별로 묶은 것)과 8비트 일련 번호가 온다.
그 구조를 기술하는 매크로들이 <asm/ioctl.h>
에 있는데, 바로 _IO(type,nr)
와 {_IOR,_IOW,_IOWR}(type,nr,size)
이다. sizeof(size)
로 쓰기 때문에 size는 사실 잘못된 이름이다. 즉, 세 번째 인자는 데이터 타입이다.
size 비트가 그리 믿을 만하지 않다. 많은 경우에 값이 잘못돼 있는데, 매크로 버그 때문에 sizeof(sizeof(struct))
로 돼서일 수도 있고 값이 갱신되지 않아서일 수도 있다.
요컨대 새 구조에는 단점만 있는 것 같다. 검사에는 도움을 주지 않으면서 아키텍처마다 값이 달라지게 만든다.
SEE ALSO
execve(2), fcntl(2), ioctl_console(2), ioctl_fat(2)
, ioctl_ficlonerange(2), ioctl_fideduperange(2), ioctl_fslabel(2), ioctl_getfsmap(2), ioctl_iflags(2), ioctl_ns(2), ioctl_tty(2), ioctl_userfaultfd(2), open(2), sd(4)
, tty(4)
2021-03-22