강좌 & 팁
안녕하세요! 호서대학교 석사(과정) 이우영 입니다.
오늘은 저번에 이어서 모든 프로세스의 정보를 조금 더 출력 해보고
자식프로세스, container_of 매크로 등에 대해서 알아 보도록 하겠습니다.
task_struct
오늘도 저번 시간처럼 for_each_process 매크로를 이용하여 프로세스의 정보를 얻어옵니다.
요번에는 PPID(부모의 PID), UID, 프로세스 상태를 추가 해보겠습니다.
2.4 커널 버전에서는 PPID가 따로 변수로 있었지만 2.6커널부터는 부모의 task_struct 주소를 갖는 parent 변수가 있습니다.
그럼 parent 의 pid 를 찍으면 부모의 프로세스 번호가 나오겠죠?
모양이 저번에 보았던 PS명령어와 비슷해졌죠? (내용은 다르지만 ㅎㅎ)
PPID를 보면 프로세스들이 어떤 프로세스로부터 생겼는지 알 수 있습니다.
UID는 PS명령어때 문자열로 출력 되었지만 선언된 변수는 shot int 형 이였습니다.
아마 번호와 문자열을 따로 가지고 있는거 같습니다. 0은 root, 99는 nobody 로 축측됩니다 ㅎㅎ.
상태가 0인것은 running 상태인 프로세스이고, 1은 stopped 상태입니다.
자식 프로세스와 list_head
이번에는 자식프로세스를 출력 해보도록 하겠습니다.
부모와 다르게 자식 프로세스는 하나 이상으로 생길 수 있습니다.
task_struct는 구조체 이기 때문에 자식 프로세스가 생길때마다 변수를 생성 할 수 없겠죠?
그래서 자식들의 정보를 링크 리스트로 연결한 list 정보를 가지고 있습니다.
list_head children; <- 요렇게 선언 되어 있습니다. 먼저 list_head를 볼까요?
/include/linux/types.h 를 보면
struct list_head {
struct list_head *next, *prev;
}
참 심플하죠? 하지만 전 보면서 의문이 들었습니다. task_struct를 가리키는 변수는 어딨는거지?
리스트를 연결하는 변수만 보이지 data를 가리키는 변수가 없습니다.
리눅스 커널 개발자들은 생각의 전환을 했습니다.
우리는 구조체를 알고 있고 children이라는 변수는 구조체 시작 주소로 부터 얼만큼 떨어져 있는지 알고 있습니다.
그림을 보면 list_head로 프로세스들이 연결 되어있습니다.
container_of 매크로를 이용하여 task_struct 의 주소를 얻어옵니다.
위에서 한번 언급 한대로 자식1 이라는 task_struct의 list_head sibling 이
task_struct의 시작 주소로 부터 얼만큰 떨여져 있는지 알고있기 때문에 주소를 얻어 올 수 있습니다.
container_of 매크로의 조금 더 자세한 내용은 이쪽을 확인 해 주세요
어느정도 이해가 되셨으면 자식의 프로세스 ID를 출력 해보겠습니다.
요번에도 리눅스 개발자들은 편리한 매크로를 만들어 두어습니다.
list_for_each( 주소가 저장되는 임시변수, 순회할 리스트 포인터) 를 이용하여
루프를 돌때마다 임시변수에 리스트의 다음 요소를 가리키고 있습니다.
리스트 만드로는 정보를 얻어올 수 없겠죠? 그래서 위에서 설명한 container_of 매크로를 한번더 거쳐야 우리가 원하는
자식 프로세스의 정보를 얻을 수 있습니다. container_of 를 단순 하게 사용하게 만들어진 list_entry를 사용해서
주소를 얻어 오고 프로세스의 ID를 출력 하였습니다.
init 프로세스인 1번은 역시나 자식들이 많은 것을 알 수 있습니다.
오늘도 간단하면서 리눅스 개발자들의 기발한 아이디어를 보았습니다.
다음에는 kprobe에 대해서 알아 보도록 하겠습니다.
(커널 디버깅을 하기위해 필요한 것입니다!)
http://ms-osek.org/ <- 쫌더 빨리 보고 싶으신분은 여기로 오세요~