ioctl

ioctl

2025년 9월 8일

ioctl (I/O control) 이란? #

ioctl이라는건 외부에서 드라이버에게 하드웨어를 어떻게 조작할건지 요청하고 드라이버는 그걸 abi 형태로 인터페이스를 노출시켜놨다 이렇게 이해하면 되나?

유저공간 → 커널드라이버 로 제어 명령을 보내는 통로

드라이버는 이 제어 명령들을 UAPI(= 사용자 공간 ABI)로 문서화/노출합니다. 즉, request 번호와 그에 대응하는 구조체 레이아웃이 “계약(ABI)”이에요.

하드웨어 상태/모드 변경(전원, 클럭, 캘리브레이션, 포맷 설정 등)처럼 read/write로 하기 애매한 작업을 수행합니다.

단, 항상 하드웨어만은 아님: TUN/TAP, loop, 가상 장치처럼 소프트웨어 디바이스의 설정도 ioctl로 합니다.

 1// int ioctl(int fd, unsigned long request, void *argp);
 2
 3// 드라이버가 헤더에 노출하는 명령들 ABI (번호는 0..N)
 4#define MY_IOC_GET_VERSION  _IOR(MY_IOC_MAGIC, 1, int)               // 커널→유저로 int 읽음
 5#define MY_IOC_SET_BUFSIZE  _IOW(MY_IOC_MAGIC, 2, unsigned long)     // 유저→커널로 ulong 씀
 6struct my_echo { uint32_t len; char data[256]; };
 7#define MY_IOC_ECHO         _IOWR(MY_IOC_MAGIC, 3, struct my_echo)   // 양방향
 8
 9// 유저영역에서 요청하는코드. 위에서 제공된 헤더를 include함 
10int main(void) {
11    // 기기 fd 얻어오기
12    int fd = open("/dev/mydev", O_RDWR);
13    if (fd < 0) { perror("open"); return 1; }
14
15    // 장치에서 버전을 가져옴. 버전 가져오는 동작을 하는 ioctl 값과 버퍼를 넘겨주면 드라이버가 그걸 채워준다. 
16    int ver;
17    if (ioctl(fd, MY_IOC_GET_VERSION, &ver) == -1) perror("GET_VERSION");
18    else printf("version=%d\n", ver);
19
20    // 내부 버퍼 사이즈 세팅하는 ioctl 요청
21    unsigned long sz = 4096;
22    if (ioctl(fd, MY_IOC_SET_BUFSIZE, &sz) == -1) perror("SET_BUFSIZE");
23
24    // 양방향 읽기쓰기 다함. 그냥 장치에서 읽은대로 다시 데이터를 채워준다. 
25    struct my_echo e = { .len = 5 };
26    memcpy(e.data, "hello", 5);
27    if (ioctl(fd, MY_IOC_ECHO, &e) == -1) perror("ECHO");
28    else printf("echo back len=%u data=%.*s\n", e.len, (int)e.len, e.data);
29
30    // 소켓 닫고 종료 
31    close(fd);
32    return 0;
33}
comments powered by Disqus