[ARM중] struct list_head 의 비밀

홍문화 2012.01.18 20:57 조회 수 : 6979

지난 스터디 시간에 나왔던 커널이 사용하는 연결 리스트에 대해 정리를 해봅니다.

struct list_head는 커널에 다음과 같이 정의 되어 있습니다.

struct list_head {
    struct list_head *next, *prev;
};

커널이 사용하는 구조체 변수들을 연결 리스트로 만들 때 자주 사용하며 상당히 간단하고 유용합니다.
다음과 같은 구조체 형이 있다고 했을 때 struct list_head 멤버를 살짝? 넣어줌으로써 구조체를 손쉽게 
연결 리스트로 만들 수 있습니다.

typedef struct bootmem_data {
    unsigned long node_min_pfn;
    unsigned long node_low_pfn;
    void *node_bootmem_map;
    unsigned long last_end_off;
    unsigned long hint_idx;
    struct list_head list;
} bootmem_data_t;

다음과 같이 구조체 변수를 세개 만듭니다.
bootmem_data_t aaa, bbb, ccc;

구조체의 멤버인 struct list_head list를 통해 연결리스트로 만들어 줍니다.
aaa.list->next = &bbb.list;
bbb.list->prev = &aaa.list;

bbb.list->next = &ccc.list;
ccc.list->prev = &bbb.list;

ccc.list->next = &aaa.list;
aaa.list->prev = &ccc.list;

그런데 여기서 문제가 발생 합니다.
구조체들을 연결 리스트로 연결해서 뽀대?가 나게 되었는데 정작 필요한 데이터를 저장하고 있는 
구조체의 멤버들에 접근 할 길이 없어 보입니다.

하지만 커널은 다음과 같이 꼼수를 발휘해서 이 난관을 극복합니다.
다음의 코드를 실행하면 offset에 얼마가 저장이 될까요?
size_t offset;
offset = &((bootmem_data_t *)0)->list

offset에는 20이 저장이 됩니다.
bootmem_data_t 타입의 구조체가 0번지에 존재한다고 가정을 했으므로
이 구조체의 첫번째 멤버인 node_min_pfn는 0번지 주소에 배치되고
두번째 멤버인 node_low_pfn는 4번지 주소에 배치되고 ... 
hint_idx 멤버는 16번지 주소에 배치 됩니다. 결국 list 멤버는 20번지 주소에 배치가 되게 되는 것입니다.

즉, 조금 전에 만들었던 구조체 변수 aaa의 시작 주소는 ((char*)&aaa.list - 20)를 통해서 구할 수 있습니다.
이제 aaa의 시작 주소를 알았으니 다음과 같이 캐스팅을 통해(bootmem_data_t *)((char*)&aaa.list - 20) 
이 구조체의 모든 멤버에 접근이 가능하게 되는 것입니다. 


그림을 그려서 좀 더 이해하기 쉽게 설명을 하고 싶은데 시간이 여의치 않네요.
잘못된 내용은 지적 부탁 드립니다.
번호 제목 글쓴이 날짜 조회 수
공지 [공지] 커널 스터디 관련 Q&A 게시판 입니다. [5] woos 2016.04.09 2202
1545 버디 알고리즘... 김범환 2007.11.11 7172
1544 책 왔네요. [1] 서정민 2010.11.08 7163
1543 [질문] 선점형 커널이란?? [4] 송형주 2007.09.11 7132
1542 [DKS - 011] Flattened Device Tree 박세율 2012.07.07 7108
1541 elf 의 실행... bin 의 실행... [4] 배병일 2010.04.14 7095
1540 Linux-ARM-Mailing List 게시판 링크 [5] 유경환 2011.08.23 7070
1539 BIG KERNEL 압축 해제 루틴 설명 자료 (2nd edition) file 지현구 2007.05.25 7067
1538 콜백 함수는... [8] 홍문화 2011.05.11 7065
1537 2진수, 16진수, 10진수 변환기 [1] file 맥주 2007.05.21 7039
1536 SMP 지원하는 u-boot source 주소입니다. [2] 박대원 2010.04.05 7023
1535 커널 스택 조사와 질문.. [5] 이종인 2011.04.03 7013
1534 [소개] ARM core 강좌 김동혁 2010.04.16 6998
1533 이번주 1주년 파티?? [2] 노서영 2010.05.24 6996
» [ARM중] struct list_head 의 비밀 [2] 홍문화 2012.01.18 6979
1531 spinlock의 이해 [8] 홍문화 2011.04.17 6949
1530 nested interrupt 관련 참조 문서 유강희 2011.07.11 6911
1529 커널 압축 해제 루틴 설명 자료 [1] file 지현구 2007.05.19 6903
1528 [소개] Cortex-A8 프로세서 아키텍처 과정 런칭 세미나 [1] 김동혁 2010.05.06 6883
1527 ARM AP의 메모리관련 정보 [7] 서정민 2011.03.21 6882
1526 WIKI 페이지 생성했습니다. [1] 권기봉 2010.04.06 6879
XE Login