강좌 & 팁
유저레벨에서 커널에 있는 API 를 동작시키는 인터페이스는 시스템 콜로써 항상 사용되는 것이다.
하지만 커널 레벨에서 사용자 공간의 어플리케이션을 실행하는 것은 그다지 알려져 있지 않다.
하지만 가만히 생각해 보면 핫플러그인과 같이 USB 가 꼽히면 자동으로 마운트되는 것을 우리는 알고 있다.
과연 어플리케이션에서 주기적으로 USB 꼽힌 것을 체크해서 마운트 하는 것일까?
그렇지 않다.
커널 레벨에서 USB가 인식되면 종류에 따라 마운트를 시켜주는 함수가 실행되게 된다.
혹은 모듈이 필요하면 모듈까지도 로딩을 시켜준다.
이런 인터페이스가 가능한 커널 함수를 소개한다.
그 인터페이시의 이름은 usermodehelper API 이다.
그 API를 한번 살펴보면
usermod 헬퍼 API 핵심함수
call_usermodehelper_setup 사용자 지역 호출을 위한 핸들러 준비
call_usermodehelper_setkeys 헬퍼의 세션 키 설정
call_usermodehelper_setcleanup 헬퍼의 정리 함수 설정
call_usermodehelper_stdinpipe 헬퍼의 stdin 파이프 작성
call_usermodehelper_exec 사용자 지역 호출 호출
이정도로 구성되어 있다.
자료구조를 살펴보면
kernel/kmod.c#L117
117struct subprocess_info {
118 struct work_struct work;
119 struct completion *complete;
120 char *path;
121 char **argv;
122 char **envp;
123 struct key *ring;
124 enum umh_wait wait;
125 int retval;
126 struct file *stdin;
127 void (*cleanup)(char **argv, char **envp);
128};
의외로 아주 간단한 구조를 갖고 있다.
이제 사용자 모드 헬퍼 API 의 내부구조를 살펴보자.
kernel_execve 를 사용하여 커널 공간 커널모듈 로더로 사용하는 구현을 한다.
kernel_execve 는 부팅시 init 프로세스를 시작하는데 사용되는 함수이며 사용자 모드 헬퍼 API는 사용하지 않는다.
사용자 모드 헬퍼의 작업은 사전 구성된 subprocess_info 구조에서 사용자 공간 애플리케이션을 시작하는 데 사용되는
call_usermodehelper_exec에 대한 호출로 시작한다. 이 함수는 subprocess_info 구조 참조와 열거 유형
(기다리지 않을 것인지, 프로세스가 시작되기를 기다릴 것인지 아니면 전체 프로세스가 완료되길 기다릴 것인지)이라는
두 가지 인수를 승인한다.
그러면 호출을 비동기로 수행하는 작업 구조(khelper_wq)로 subprocess_info(또는 이 구조의 work_struct 요소)가 큐에 삽입된다.
그림....
요소가 khelper_wq에 배치되면 작업 큐에 대한 핸들러 함수(이 경우에는 __call_usermodehelper)가 호출되어
khelper 스레드를 통해 실행된다.
이 함수는 사용자 공간 호출에 필요한 모든 정보가 포함된 subprocess_info 구조를 큐에서 제거하여 시작된다.
다음 경로는 wait 변수 열거에 따라 다르다. 요청자가 전체 프로세스가 완료될 때까지 기다리길 원하는 경우
(사용자 공간 호출(UMH_WAIT_PROC) 또는 전혀 기다리지 않음(UMH_NO_WAIT) 포함) 커널 스레드가
wait_for_helper 함수에서 작성된다.
그렇지 않으면 요청자는 단순히 사용자 공간 애플리케이션이 호출될 때까지 기다리고(UMH_WAIT_EXEC) 완료될 때까지는
기다리지 않으려고 한다.
이 경우 커널 스레드는 ____call_usermodehelper()를 위해 작성된다.
call_usermodehelper_exec -> khelper_wq 등록 -> run subprocess_info->work ( __call_usermodehelper ) ->
___call_usermodehelper() ->call_usermodehelper_freeinfo()
와 같은 일련의 과정을 따르고 중간에 wait 냐 no wait 냐에 따라 중간 처리가 달라진다.
안녕하세요,
usermode helper관련 설명 정말 잘 봤습니다.
한가지 질문이 있는데요, 중간에
<위의 예제가 logger 가 아니라 printf("hello world\n"); 를 실행하는 예제라면