Container_of 매크로

Posted by ironmask84
2016. 11. 9. 11:01 나는 프로그래머다!/Linux


Linux 소스 스터디 입문을 했습니다.

"리눅스 커널과 디바이스드라이버 실습2" 라는 책을 구입 후 보는 중인데,
리눅스에서 주로 사용하는 자료구조 쪽을 공부하다보니,
(기준 리눅스 커널 버젼은 2.6.31 이라고 합니다.)

소스 내에 container_of(ptr, type, member) 이라는 매크로를 소개하네요..
이름만 봐서는 argument들의 container.. 즉, C언어이니 구조체를 리턴해줄 것으로 보이는데,
container의 주소값을 얻는데 사용하는 것 같습니다.

첫 느낌은 뭔가 디게 복잡하게 주소값을 얻어오는 기분입니다만.. 이게 최선인가;;
매크로는 아래와 같습니다.

#define offsetof(TYPE, MEMBER) ((unsigned long) & ((TYPE *)0)->MEMBER)

#define container_of(ptr, type, member) ({ \

const typeof( ((type *)0)->member ) *_mptr = (ptr); \

(type *)( (char *)_mptr - offsetof(type, member) ); })

실제로 console로 결과값을 돌려보고, 머리를 굴려봐도 머리에 잘 안들어오네요 ㅜㅜ

검색하다가 리뷰가 잘되어있는 주소 링크합니다.
http://rootfriend.tistory.com/197
http://kldp.org/node/58409

주요내용은 아래에 따로 펌~

gcc C 언어 확장 기능으로, (즉, 표준이 아니며, 다른 컴파일러에서 지원하지 않는..) compound statement (중괄호로 둘러싼 여러 statement)를 expression으로 해석하는 기능이 있습니다. 예를 들면:

({ int y = foo(); int z;
if (y > 0) z = y;
else z = - y;
z; })


로 쓴 것처럼, foo() 리턴 값의 절대값을 얻는 코드를 위와 같이 작성할 수 있습니다. 이 것은 C99 표준에서 inline function이 나오기 전에 매우 유용하게 썼던 기능입니다. expression에서 switch, for 등의 statement를 쓸 수 있는 등의 장점을 얻을 수 있었습니다. 실제로 GNU C library에 포함되어 있는 obstack에 관계된 대부분의 함수가 이 compound-statement expression을 써서 macro로 구현되어 있습니다. 물론 맨 마지막 statement의 값이, 이 compound statement의 값이 됩니다.

그런데, 이 기능은 현재 C++에서 쓸 경우, 임시 변수의 destructor가 불리는 순서가 바뀌는 등의 단점이 있기 때문에, C++로 쓸 우려가 있는 코드에서는 이 compound statement expression을 쓰지 말라고 권하고 있습니다.

개인적으로 간단한 수식으로 나올 수 있는 것이 아니라면 do { ... } while (0)을 써서 macro로 만들고, 어떤 값을 리턴할 필요가 있는 macro라면 inline function을 쓰는 것이 좋다고 생각합니다.