ioctl
ioctl (I/O control) 이란?
ioctl이라는건 외부에서 드라이버에게 하드웨어를 어떻게 조작할건지 요청하고 드라이버는 그걸 abi 형태로 인터페이스를 노출시켜놨다 이렇게 이해하면 되나?
유저공간 → 커널드라이버 로 제어 명령을 보내는 통로
드라이버는 이 제어 명령들을 UAPI(= 사용자 공간 ABI)로 문서화/노출합니다.
즉, request 번호와 그에 대응하는 구조체 레이아웃이 “계약(ABI)”이에요.
하드웨어 상태/모드 변경(전원, 클럭, 캘리브레이션, 포맷 설정 등)처럼 read/write로 하기 애매한 작업을 수행합니다.
단, 항상 하드웨어만은 아님: TUN/TAP, loop, 가상 장치처럼 소프트웨어 디바이스의 설정도 ioctl로 합니다.
// int ioctl(int fd, unsigned long request, void *argp);
// 드라이버가 헤더에 노출하는 명령들 ABI (번호는 0..N)
#define MY_IOC_GET_VERSION _IOR(MY_IOC_MAGIC, 1, int) // 커널→유저로 int 읽음
#define MY_IOC_SET_BUFSIZE _IOW(MY_IOC_MAGIC, 2, unsigned long) // 유저→커널로 ulong 씀
struct my_echo { uint32_t len; char data[256]; };
#define MY_IOC_ECHO _IOWR(MY_IOC_MAGIC, 3, struct my_echo) // 양방향
// 유저영역에서 요청하는코드. 위에서 제공된 헤더를 include함
int main(void) {
// 기기 fd 얻어오기
int fd = open("/dev/mydev", O_RDWR);
if (fd < 0) { perror("open"); return 1; }
// 장치에서 버전을 가져옴. 버전 가져오는 동작을 하는 ioctl 값과 버퍼를 넘겨주면 드라이버가 그걸 채워준다.
int ver;
if (ioctl(fd, MY_IOC_GET_VERSION, &ver) == -1) perror("GET_VERSION");
else printf("version=%d\n", ver);
// 내부 버퍼 사이즈 세팅하는 ioctl 요청
unsigned long sz = 4096;
if (ioctl(fd, MY_IOC_SET_BUFSIZE, &sz) == -1) perror("SET_BUFSIZE");
// 양방향 읽기쓰기 다함. 그냥 장치에서 읽은대로 다시 데이터를 채워준다.
struct my_echo e = { .len = 5 };
memcpy(e.data, "hello", 5);
if (ioctl(fd, MY_IOC_ECHO, &e) == -1) perror("ECHO");
else printf("echo back len=%u data=%.*s\n", e.len, (int)e.len, e.data);
// 소켓 닫고 종료
close(fd);
return 0;
}