jinb-park blog

Security, Network, OS, Linux, Kernel

ioctl, unlocked_ioctl, compat_ioctl 차이점

댓글 3

Linux/Linux Kernel

2015. 12. 30.



작성자 : 박진범
메일 : jinb.park7@gmail.com


:) ioctl

int (*ioctl)( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg )

- 2.6 버전부터 사라진 필드이다.
- BKL (Big Kernel Lock) 으로 보호되어 동작되었다. BKL 이란 모든 CPU 에 대한 전체 Lock을 의미한다. 리눅스에서는 UserSpace 에서 KernelSpace 로 접근할 때 BKL 을 잡고, 다시 UserSpace 로 리턴할 때 BKL 을 릴리즈했다고 한다.
  이 말은 한 순간에 하나의 User Process 만이 KernelSpace 에서 동작할 수 있도록 한다는 의미이다. 
- 하지만 BKL 을 한 CPU 에서 잡고 있을 때, 다른 User Process 는 Kernel Space 동작을 계속 대기해야 하므로, SMP 환경에서 상당히 비효율적인 방법이다.
- 원래 리눅스는 SMP 환경을 고려하지 않고 만들어졌었다고 한다. 따라서 SMP 가 처음 도입되었을 때, 그에 대한 Locking 방법이 필요했고, 가장 Simple 한 방법인 BKL 이 도입되었었다.
- BKL 은 2.6.39 버전부터 제거되었다.

:) unlocked_ioctl

long (*unlocked_ioctl) (struct file *filp, unsigned int cmd, 
                            unsigned long arg);

- BKL 을 사용하지 않고, 자기 자신의 Lock 을 사용하는 unlocked_ioctl 필드가 file_operations 구조체에 추가되었다. 이를 통해 SMP 환경에서 여러 User Process 가 동시에 KernelSpace 에서 동작이 가능해졌다.
- 함수 원형을 보면, inode 파라미터가 사라지고 file 파라미터만 남아있는데, 이는 inode 는 모든 프로세스에서 공유 가능한 것이지만, file 은 현재 프로세스 컨텍스트에서만 사용하는 것이기 때문에, file 에만 접근하라고 명시적으로 표현한 것이라고 생각된다. (확실한 동기화를 위해)

:) compat_ioctl

long (*compat_ioctl) (struct file *filp, unsigned int cmd, 
                          unsigned long arg);

- 64bit system (kernel) 에 32bit 유저 프로세스가 ioctl 요청하는 경우를 위해 만들어진 함수이다. 즉, 32bit 프로세스의 ioctl 요청을 64bit 커널에서 처리하기 위해서 (그 반대 경우도) 변환을 담당하는 것이 이 함수이다.
- 32/64 bit 이슈에 확실히 대응하기 위해선, 영향을 받는 타입 변수를 사용하지 않으면 된다. (void*, long 등)
커널코드를 아직 정확히 보질 않아서 이 함수가 어떻게 변환을 수행하는지는 잘 모르겠다.;


:) References