강좌 & 팁
디바이스 드라이버 작업을 하다 보면 자주 보게 되는 매크로중으 히나가
바로 container_of 매크로 입니다.
이해가 가는 것 같기도 하고 아니것 같기도 하고 묻는 사람도 있고 해서
오늘은 이 매크로에 대해서 한번 알아 볼가 합니다.
일단 함수 원형을 한번 볼까요?
lxr 사이트에서 긁어 왔습니다.
위치는 include/linux/kernel.h 입니다.
650#define container_of(ptr, type, member) ({ \ 651 const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 652 (type *)( (char *)__mptr - offsetof(type,member) );})
이건 뭐 상당히 거시기 하군요.
뜯기 전에 좀 쉬운 예를 들어 보겠습니다.
위의 그림이 보이십니까?
뽀글이 structure 는 인자가 4개 입니다.
시작 번지는 1000 번지구요.
라면 번지 1000
수프 번지 1008
가격 번지 1016
봉지 번지 1020
이렇게 되는 군요.
그런데 어떤 함수를 호출하면서 가격의 포인터를 넘겨주었습니다.
그래서... 가격포인터를 인자로 받은 함수가 아래와 같습니다.
int how_much( short *가격)
{
printk(" 가격위치는 0x%p\n", 가격)
return 0;
}
자 이제 how_much 함수는 가격포인터를 프린트해줍니다.
당연히 그 값은 1016 번지가 되겠죠.
자 이제 how_much 함수는 가격의 포인터를 알고 있습니다.
처음 그림에서 보면 가격 인자는 뽀글이 자료 구조의 멤버네요?
how_much 에서 short * 형태로 인자를 받았지만
그 포인터가 struct 뽀글이 멤버라는 것을 알고 있고
struct 뽀글이 다른 멤버를 필요로 하는 경우가 생겼습니다.
쉽게 얘기해서 내가 받은 인자를 이용해서 그 인자를 포함하고 있는
자료구조가 필요한 것입니다.
직관적으로 그림에서 보면 뽀글이 자료구조의 주소는 1000 번지 입니다.
가격 포인터가 1016 이므로 16 만 빼면 1000 번지가 나오죠?
이제 우리는 struct 뽀글이 의 변수 위치를 찾은겁니다.
함수를 다시 써보죠.
int how_much( short *내가격)
{
struct 뽀글이 *myboggle = containerof(내가격, struct 뽀글이, 가격);
printk(" 내가격을 멤버로 갖는 boggle 구조체의 위치는 0x%p\n", myboggle)
myboggle->라면 = 봉지라면;
return 0;
}
이 결과는 0x1000 이 나오게 됩니다.
컨테이너 매크로에서 필요한 것은 세가지 조건입니다.
현재 알고 있는 변수포인터.
구조체함수원형.
구조체멤버의 변수명.
복잡해 보이기도 하지만 결론적으로는
1000 = container_of(1006, struct 뽀글이, 가격)
이렇게 되는데 1006 이라는 위치를 가르쳐주고
1006 이 뽀글이의 가격이라는 멤버의 주소이다.
뽀글이 구조체에서 가격의 변수 위치는 항상 6이라는 오프셋이니까
1006 - 6 = 1000.
이렇게 되도록 짜여져 있는 매크로 입니다.
복잡한가요?
정리합니다.
container_of (prt, type, member)
prt : 임의의 포인터값.
type : ptr 을 멤버로 갖는 자료구조형(구하고자 하는 자료구조의 형).
member : 자료구조형에서 ptr 의 멤머 이름.
전에 만들어놓은 파일에 이와 관련된 부분이 있어서, 한번 올려 봅니다...