Linux 커 널 컨테이너매크로 정의 분석
3435 단어 Container_of
1. \ # define offstof (TYPE, MEMBER) (size t) & (TYPE *) 0) - > MEMBER) 1. (TYPE *) 0) 0 을 TYPE 타 입 포인터 로 변환 합 니 다.2. (TYPE *) 0) - > MEMBER 액세스 구조의 데이터 구성원;3. & (TYPE *) 0) - > MEMBER) 데이터 구성원 의 주 소 를 추출 합 니 다.4. (size t) (& ((TYPE *) 0) - > MEMBER) 결과 변환 유형;교묘 한 점 은 0 을 (TYPE *) 로 바 꾸 고 구 조 는 메모리 공간의 첫 번 째 주소 0 을 시작 주소 로 하면 구성원 의 주 소 는 자 연 스 럽 게 오프셋 주소 가 된다 는 것 이다.예 를 들 어 설명:
#include<stdio.h>
typedef struct _test
{
char i;
int j;
char k;
}Test;
int main()
{
Test *p = 0;
printf("%p
", &(p->k));
}
답: 0000008
자기 분석: 여기 서 사용 하 는 것 은 컴 파일 러 기술 을 이용 한 작은 기법 이다. 즉, 구조 구성원 변수 가 구조 체 에서 구조 체 에 비해 첫 번 째 주소 의 오프셋 주 소 를 먼저 구 한 다음 에 구조 체 의 첫 번 째 주소 가 0 이라는 것 을 알 수 있다. 이 오프셋 주 소 는 바로 이 구조 체 변수 가 이 구조 체 에서 의 오프셋 이다.즉, 이 구조 체 구성원 변 수 는 구조 체 의 첫 번 째 거리 이다.offstof () 에서 이 member 구성원 의 주 소 는 실제 type 데이터 구조 에서 member 구성원 이 구조 변수 에 비해 오프셋 입 니 다.주어진 구조 에 대해 offstof (type, member) 는 상수 입 니 다. listentry () 는 바로 이 변 하지 않 는 오프셋 을 이용 하여 링크 데이터 항목 의 변수 주 소 를 구 하 는 것 입 니 다.
2. containerof() container_of () 는 \ \ linux \ kernel. h 에서 왔 습 니 다.
:container_of - cast a member of a tructure out to the containing structure。
ptr: the pointer to the member.
type: the type of the container struct this is embedded in.
member:the name of the member within the truct.
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
자기 분석: 1. (type *) 0 - > member 는 type 유형의 구조 체 를 설계 하기 위해 시작 주 소 는 0 이 고 컴 파일 러 는 구조 체 의 시작 주 소 를 이 구조 체 구성원 변수의 오프셋 을 더 해서 이 구조 체 구성원 변수의 오프셋 주 소 를 얻 을 수 있 습 니 다. 구조 체 의 시작 주 소 는 0 이기 때 문 입 니 다.따라서 이 구조 체 구성원 변수의 오프셋 주 소 는 구성원 변수 가 구조 체 내의 거리 구조 체 시작 부분의 오프셋 과 같다.즉: & (type *) 0 - > member 는 구성원 변수의 오프셋 주 소 를 추출 하 는 것 입 니 다.이 는 구조 체 내 에서 의 오프셋 과 같다. 즉, (size t) (& (type *) 0) - > member) 는 size 를 거 친다.t 의 강제 유형 전환 후 그 수 치 는 구조 체 내의 편 이 량 이다.이 오프셋 은 offstof () 에서 구 합 니 다.2. type of ((type *) 0) - > member) 는 member 구성원 의 변수 형식 을 추출 합 니 다.그 정의 로mptr 포인터. ptr 는 이 구성원 변 수 를 가리 키 는 포인터 입 니 다.mptr 는 member 데이터 형식의 상수 포인터 로 ptr 가 가리 키 는 변 수 를 가리킨다.3.(char *)__mptr 를 바이트 형 포인터 로 변환 합 니 다.(char *)__mptr - offsetof (type, member) 는 구조 체 의 시작 주소 (char * 형 포인터) 를 구하 고 (type *) (char *) ((char *) mptr - ofsetof (type, member) 는 (type *) 작용 하에 바이트 형의 구조 체 시작 지침 을 type * 형의 구조 체 시작 지침 으로 전환한다.4. ({}) 이 확장 자 는 프로그램 블록 의 마지막 표현 식 값 을 되 돌려 줍 니 다. 이것 이 바로 구조 체 의 한 구성원 변수 지침 에서 이 구조 체 의 첫 번 째 지침 을 구 하 는 것 이다.포인터 유형 은 구조 체 의 한 구성원 변수 유형 에서 이 구조 체 유형 으로 바 뀌 었 다.
= = = = = = = = = = = = = = = = = = = 없어 서 는 안 될 총 결 = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =어떻게 정상적으로 사용 할 수 있 습 니까?구조 체 는 컴 파 일 러 가 주 소 를 분배 해 야 하기 때문에 자신 이 값 을 부여 하면 구조 체 에 값 을 부여 하면 메모리 불법 접근 과 같은 문제 가 발생 할 수 있다.예 를 들 어 첫 번 째 예 를 수정 하면 다음 과 같다.
#include<stdio.h>
typedef struct _test
{
char i;
int j;
char k;
}Test;
int main()
{
Test *p = 0;
printf("%p
", &(p->k));
p->k = 'a';
}
코드 p->k = 'a'; 프로그램 이 실 행 될 때 Segmentation fault (core dumped) 가 발생 합 니 다.그러나 첫 번 째 예 는 구조 체 의 한 구성원 의 주 소 를 얻 었 을 뿐 이 주 소 를 읽 거나 쓰 지 않 았 음 을 주의 하 세 요.