- vừa được xem lúc

Triển khai container_of trong C

0 0 5

Người đăng: Nguyễn Đặng Triều

Theo Viblo Asia

Mở đầu

Để có thể hiểu về contaier_of, trước hết cần phải hiểu offsetof() trong thư viện stddef.h

Thế offsetof(): dùng để làm gì ?

  • Macro này sẽ trả về 1 giá trị kiểu size_t.
  • Giá trị này là khoảng cách các byte của member trong struct.

Hãy xem ví dụ sau đây để có thể hiểu rõ hơn về cách sử dụng offsetof()

#include <stdio.h>
#include <stdint.h>
#include <stddef.h> struct Register{ uint8_t setup[2]; uint8_t input; uint8_t output[3];
}; int main()
{ printf("setup offset: %d\n", offsetof(struct Register, setup)); printf("input offset: %d\n", offsetof(struct Register, input)); printf("output offset: %d\n", offsetof(struct Register, output)); printf("Size cua struct Register: %d\n", sizeof(struct Register));
}

Output

setup offset: 0
input offset: 2
output offset: 3
Size cua struct Register: 6

Như có thể thấy kết quả ở đây, thì

  • setup nằm ở vị trí đầu tiên, nên offset so với struct Register sẽ là 0.
  • input nằm ở vị trí thứ 2, và offset so với struct Register là 2. Câu hỏi: "Tại sao lại là 2 mà không phải là giá trị nào khác ?"
    • Bởi vì 2 byte đầu tiên do, setup đã chiếm trong struct Register nên input nằm ở vị trí byte thứ 3.
  • Tương tự, outputoffset = 3 , chiếm vị trí bắt đầu ở byte 4.

image.png

Tại vì sao, tôi lại tìm hiểu vấn đề này ?

Trong quá trình phát triển 1 os theo kiến trúc event-driven, os này dành cho dự án IoT cá nhân của tôi. Có 1 vấn đề xảy ra, cùng không hẳng là vấn đề hihi.

Mô tả như sau:

Tôi có 1 list gọi là Ready list - chứa những task sẵn sàng chạy Ở đây tôi dùng Double linked list để lưu trữ những task ready này.
struct Dlist
{ DNode first; DNode last; size; } struct DNode
{ DNode next; DNode prev;
} struct Task
{ DNode Node_task; // đại diện task trong ready list int data; ....
}

Đây là một đoạn mã đơn giãn để tôi có thể lưu trữ các task này vào DList, nhưng 1 vấn đề là khi mà ta lưu trữ task dưới dạng node trong list thì list đó sẽ không nhận diện được task nào đang nắm giữ node đó, mặc dù node có ở trong list.

  • Lúc này ta cần phải tạo 1 con trỏ để có thể trỏ tới task đang nắm giữa node này

image.png

Lúc này, cần phải chỉnh sửa struct DNode một tý

struct DNode
{ struct Task* Qwner; DNode next; DNode prev;
}

Lúc này thì con trỏ Qwner sẽ trỏ tới task dang nắm giữ node này. OK => Thế là vấn đề trên đã được giải quyết.

Nhưng chưa dùng lại ở đó, tôi đã tìm hiểu được 1 pp hay hơn, không cần phải thêm con trỏ vào struct như trên => Tiết kiệm được 1 phần memory.

Đó chỉnh là sử dụng container_of

Khái niệm: dùng địa chỉ của member trong struct để có thể tính ra được địa chỉ của struct đang nắm giữa member này Theo ví dụ trên: ta sẽ dựa vào dịa chỉ của DNode chứa trong struct Task, để có thể tìm ra dược địa chỉ của Task nắm giữa node này.

Bình luận

Bài viết tương tự

- vừa được xem lúc

Memory layout của một chương trình C/C++

1. Đặt Vấn Đề.

0 0 58

- vừa được xem lúc

Sự khác nhau giữa bộ nhớ Heap và bộ nhớ Stack trong lập trình

1. Giới thiệu. . Như chúng ta đã biết thì việc Quản lý bộ nhớ đối với một lập trình viên là rất quan trọng.

0 0 72

- vừa được xem lúc

Tích hợp thư viện C/C++ vào một dự án Flutter như thế nào?

Chào các bạn hôm nay rảnh rỗi thì mình viết một bài hướng dẫn về cách tích hợp một thư viện C/C++ vào một dự án Flutter. Thì cũng khá đơn giãn thôi vì Flutter đã cũng cấp cho chúng ta một thư viện khá

0 0 76

- vừa được xem lúc

Programming

Definition of Programming. .

0 0 50

- vừa được xem lúc

Gọi hàm của C++ trong Python bằng ctypes

Nếu đã từng dùng qua các thư viện liên quan đến toán học của Python như numpy, các bạn sẽ để ý thấy các nó có tốc độ xử lý rất nhanh. Điều này là do một phần của package này được viết bằng C/C++ và ph

0 0 51

- vừa được xem lúc

Build ứng dụng Cross Platform với Go và CGO

1. Giới thiệu.

0 0 52