macro conatainer_of () trong Nhân Linux -
Khi nói đến việc quản lý một số cấu trúc dữ liệu trong mã, hầu như bạn sẽ luôn cần phải nhúng một cấu trúc này vào một cấu trúc khác và truy xuất chúng bất cứ lúc nào mà không bị đặt câu hỏi về khoảng trống hoặc ranh giới bộ nhớ. Giả sử bạn có một người có cấu trúc, như được định nghĩa ở đây:
struct person {
int age;
int salary;
char *name;
} p;
Bằng cách chỉ có một con trỏ về tuổi hoặc mức lương, bạn có thể truy xuất toàn bộ cấu trúc bao bọc (chứa) con trỏ đó. Như tên đã nói, macro container_of được sử dụng để tìm vùng chứa của trường nhất định của một cấu trúc. Macro được định nghĩa trong include / linux / kernel.h và trông giống như sau:
#define container_of(ptr, type, member) ({ \
const typeof(((type *)0)->member) * __mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member)); })
Đừng sợ những con trỏ; chỉ cần xem chúng như sau:
container_of(pointer, container_type, container_field);
Dưới đây là các phần tử của đoạn mã trước:
- con trỏ: Đây là con trỏ đến trường trong cấu trúc
- container_type: Đây là kiểu cấu trúc bao bọc (chứa) con trỏ
- container_field: Đây là tên của trường mà con trỏ trỏ đến bên trong cấu trúc
Hãy xem xét vùng chứa sau:
struct person {
int age;
int salary;
char *name;
};
Bây giờ, hãy xem xét một trong các trường hợp của nó, cùng với một con trỏ đến thành viên tuổi:
struct person somebody;
[...]
int *age_ptr = &somebody.age;
Cùng với một con trỏ đến thành viên tên (age_ptr), bạn có thể sử dụng macro container_of để lấy một con trỏ đến toàn bộ cấu trúc (vùng chứa) bao bọc thành viên này bằng cách sử dụng như sau:
struct person *the_person;
the_person = container_of(age_ptr, struct person, age);
container_of tính đến phần bù của age ở đầu struct để có được vị trí con trỏ chính xác. Nếu bạn trừ phần bù của tuổi trường khỏi con trỏ age_ptr, bạn sẽ nhận được vị trí chính xác. Đây là những gì dòng cuối cùng của macro thực hiện:
(type *)( (char *)__mptr - offsetof(type,member) );
Áp dụng điều này vào một ví dụ thực tế, sẽ đưa ra kết quả sau:
struct family {
struct person *father;
struct person *mother;
int number_of_sons;
int family_id;
} f;
[...]
int *fam_id_ptr = &f.family_id;
struct family *fam_ptr;
fam_ptr = container_of(fam_id_ptr, struct family, family_id);
Macro container_of chủ yếu được sử dụng trong các vùng chứa chung trong hạt nhân.
Đó là tất cả về macro container_of trong kernel.
rb_node
.