사용자 응용프로그램에서 디바이스 드라이버와 서로 데이터를 주고받기 위해서는 보통 read()나 write()  함수를 사용한다.

반면 응용프로그램에서 ioctl() 함수는 복잡한 기능의 디바이스를 제어하기 위해 사용한다.

 

응용 프로그램에서 호출하는 ioctl 함수 포맷 : int ioctl(int d, int request, ....)

 

여기서 ioctl 함수의 첫 번째 인수는 open 함수로 오픈된 디바이스 파일을 가리키는 파일 디스크립터이다. 두 번째 인수는 디바이스 드라이버 내에서 사용하기 위해 정의된 명령어 번호이다. ioctl 함수의 세번째 인수가 '....'인 것은 세번째 인수가 char 타입, long타입, pointer 타입 등 여러가지 데이터 타입을 가질 수 있어 컴파일 시 인수 타입 불일치로 인한 에러 발생을 막기 위한 것이다.

 

위의 ioctl() 함수의 두 번째 인수인 명령어 번호는 보통 디바이스 드라이버 개발자가 할당한다. 리눅스 커널에서는 이 명령어 번호를 쉽게 관리할 수 있는 매크로를 제공한다.

 

 

매크로 

기능 

_IO(type,nr) 

ioctl() 함수의 세 번째 인수를 사용하지 않을 때 사용 

_IOR(type, nr, size) 

ioctl() 함수의 세 번째 인수가 디바이스 드라이버에서 read될 때 사용 

)IOW(type, nr, size) 

ioctl() 함수의 세 번째 인수가 디바이스 드라이버로 write될 때 사용 

_IOWR(type, nr, size)

ioctl() 함수의 세 번째 인수가 읽기/쓰기/동작에 모두 사용될 때 사용 

 

 

아래에 LCD 디스플레이 디바이스 드라이버에서 매직넘버 및 ioctl() 함수의 명령어를 정의하는 예를 보였다.

 

#define LCD_DEV_MAGIC 'Y'

 

#define LCD_INIT _IO(LCD_DEV_MAGIC,0)

#define LCD_CMD _IOW(LCD_DEV_MAGIC, 1, unsigned char)

#define LCD_FILL _IOW(LCD_DEV_MAGIC, 2, unsigned char)

 

위 예에서 ioctl() 함수의 LCD_INIT 명령은 사용자 응용 프로그램과 디바이스 드라이버 사이에서 데이터 전달이 필요 없는 명령이어서 _IO 매크로를 사용하였다. LCD_CMD, LCD_FILL 명령은 사용자 응용 프로그램에서 디바이스 드라이버로 데이터를 보내는(write) 기능이므로 _IOW() 매크로를 이용하였다. 이때 전달하는 데이터는 1바이트 문자로 하였다. 

 

사용자 실행 프로그램에서 위와 같이 ioctl() 함수를 호출하면 해당 디바이스 드라이버에서 file_operations 구조체가 가리키는 ioctl 함수가 호출된다

 

file_operations->(*ioctl) (struct inode*, struct file *, unsigned int, unsigned long)

 

 

 

블로그 이미지

종환 Revolutionist-JongHwan

github.com/alciakng 항상 겸손하자.