在nginx原始碼中,用了大量的資料結構,現對在nginx原始碼中對資料結構常用的一種方法進行一些總結,
nginx的事件模塊的資料結構中定義了兩個變數:timer,queue;結構體如下:
struct ngx_event_s {
void *data;
……
ngx_rbtree_node_t timer;
ngx_queue_t queue;
……
};
其實timer變數是為了將ngx_event_s結構體能掛在一個紅黑樹結構上去;而queue變數則是為了將ngx_event_s結構體能掛在一個佇列結構上去;后續借助offsetof()函式指向所查找結構體的初始位置,
下面舉一個比較容易理解的案例,對這種思想進一步加深理解,假如有一個學生的資料結構如下:
typedef struct {
int ID;
char name[10];
int age;
} student;
如果想將所有學生的資訊存盤在一個雙向鏈表里,按照nginx處理資料結構的思想會出現如下結構體:
typedef struct {
my_queue *pre;
my_queue *next;
} my_queue;
typedef struct {
int ID;
char name[10];
int age;
my_queue queue;
} student;
每個student結構體中的queue變數中的pre指標指向前一個student結構體中的queue變數; next指標指向后一個student結構體中的queue變數;結構圖如下:

遍歷佇列結構時,可通過offsetof()函式技術queue變數在結構體的相對位置,然后計算出Student 結構體的相對位置,
具體案例代碼如下:
/*******************************
* data: 2021-10-28
* author: lijd
*******************************/
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
typedef struct tMy_queue my_queue;
typedef struct {
my_queue *pre;
my_queue *next;
} tMy_queue, *pMy_queue;
typedef struct {
int Id;
char name[10];
int age;
tMy_queue queue;
} tStudent, *pStudent;
// 定義佇列頭指標
static pMy_queue ptrQueueHead = NULL;
// 佇列頭上加一個元素
void add_my_queue(pMy_queue ptrNode)
{
ptrNode->next = ptrQueueHead;
ptrNode->pre = NULL;
if(ptrQueueHead != NULL)
{
ptrQueueHead->pre = ptrNode;
}
ptrQueueHead = ptrNode;
}
// 初始化佇列結構
void init_func()
{
int i = 0;
pStudent ptrStu = NULL;
for(i = 0; i < 10; i++)
{
ptrStu = (pStudent)malloc(sizeof(tStudent));
memset(ptrStu, 0, sizeof(tStudent));
ptrStu->Id = i;
snprintf(ptrStu->name, 10, "Stu%d", i);
ptrStu->age = 18 + i;
add_my_queue(&ptrStu->queue);
}
}
pStudent find_func(int studentId)
{
pMy_queue ptr_queue = ptrQueueHead;
pStudent ptr_student = NULL;
while(ptr_queue){
// 獲取queue結構所屬的student結構
ptr_student = (pStudent)((char *)ptr_queue - offsetof(tStudent, queue));
if(ptr_student->Id == studentId)
{
return ptr_student;
}
ptr_queue = ptr_queue->next;
}
return NULL;
}
void exit_func()
{
pStudent ptrStu = NULL;
pMy_queue ptrQue = NULL;
while(ptrQueueHead)
{
ptrQue = ptrQueueHead;
if(ptrQueueHead->next)
{
((pMy_queue)(ptrQueueHead->next))->pre = NULL;
}
ptrQueueHead = ptrQueueHead->next;
// 獲取queue結構所屬的student結構
ptrStu = (pStudent)((char *)ptrQue - offsetof(tStudent, queue));
// 釋放資源
free((void *)ptrStu);
}
}
int main(int argc, char *argv[])
{
pStudent ptrStu = NULL;
init_func();
// 查找Id為6的學生
ptrStu = find_func(6);
if(ptrStu != NULL)
{
printf("Id:%d, name:%s, age:%d\n", ptrStu->Id, ptrStu->name, ptrStu->age);
}
exit_func();
return 0;
}
執行結果如下:

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/340694.html
標籤:其他
