Nginx source code analysis: ngx_queue_t

Nginx source code analysis: ngx_queue_t

Source file path

src\core\Ngx_queue.h
src\core\Ngx_queue.c

Main role analysis

ngx_queue_tIs Nginxthe doubly linked list provided .

A doubly linked list in the usual sense looks like this:

struct double_link_s {
    int            node;
    double_link_t *prev;
    double_link_t *next;
};

Contains three elements: node data data, a pointer to the previous node and a pointer prevto the next node next.

Then there are the old-fashioned creation, insertion, deletion, etc. of doubly linked lists. I won’t go into details, just google it yourself.

In fact, if you take a closer look, you will find that the operations on doubly linked lists are basically centered prevand nextunfolded, and datahave little to do with node data .

Therefore, abstracting the operation of the doubly linked list and forming an abstraction that has nothing to do with the nodes of the linked list can help us better operate the doubly linked list of various node types.

This feature is only linked list prevand nexttwo variables, there is no representation of member variables list node. Therefore, this kind of linked list is also called a lightweight linked list .

At the same time, because this kind of linked list has no node member variables, it needs to exist as a member variable of a structure with node variables. In this case, this kind of linked list is called a hosted linked list , and the structure where the linked list is located is called a host .

Take a chestnut, it grows like this:

typedef double_link_s double_link_t;
struct double_link_s {
    double_link_t *prev;
    double_link_t *next;
};

struct node_s {
    int             node;
    double_link_t   link;
}

Simply put, if you want to use the structure as a linked list node, then add this lightweight linked list to itself as a member variable .

The schematic diagram is as follows:

image description

In this way, the operation linked list is a lightweight linked list in the operation linked list, therefore, a general linked list structure can be defined.

In Nginx, this general doubly linked list structure is ngx_queue_t. This is not Nginxinvented, and Linuxthis kind of linked list is also used in the kernel.

data structure

ngx_queue_t

According to the above analysis, it is very simple to define a lightweight linked list.

typedef struct ngx_queue_s  ngx_queue_t;

struct ngx_queue_s {
    ngx_queue_t  *prev;
    ngx_queue_t  *next;
};

ngx_queue_tManagement and use

Since it is a doubly linked list, the basic operations on doubly linked lists are the same. Therefore, there is no need to explain more, just look at the source code.

ngx_queue_tinitialization

#define ngx_queue_init(q)                                                     \
    (q)->prev = q;                                                            \
    (q)->next = q

Use ngx_queue_tthe variable of the type to qinitialize the linked list. Because it is initialized, the prevsum nextpoints to itself. qAs an empty node for managing the entire linked list.

Determine ngx_queue_twhether it is empty

#define ngx_queue_empty(h)                                                    \
    (h == (h)->prev)

Insert operation

#define ngx_queue_insert_head(h, x)                                           \
    (x)->next = (h)->next;                                                    \
    (x)->next->prev = x;                                                      \
    (x)->prev = h;                                                            \
    (h)->next = x

Although the name of the macro is called insert_head, it can actually be a general operation for inserting. So, in the source code

#define ngx_queue_insert_after   ngx_queue_insert_head

There is no difference from the normal double-linked list insertion operation.

How to get the linked list node

One problem that cannot be avoided when using a boarding linked list is how to obtain the data of a node according to the linked list.

The basic idea to solve here is as follows:

  1. The host linked list is a member variable of the linked list node structure. Although the structure may be spatially discontinuous due to alignment issues, the entire structure itself can still be regarded as a continuous memory area.
  2. Therefore, you can use a offsetofmacro to calculate the offset of the member variables of the host linked list relative to the starting position of the structure
  3. The starting address of the host list-the offset of the member variables of the host list from the beginning of the structure = the start address of the structure

Therefore, ngx_queue_tthe above method is used to obtain node data

#define ngx_queue_data(q, type, link)                                         \
    (type *) ((u_char *) q - offsetof(type, link))

Among them qis the variable typeof the host list, the type of the structure where the host list is located, and the name of the variable linkin the typestructure of the host list .
This macro returns the first address of the host structure.

Get the intermediate node of the doubly linked list

This is an old stalk of doubly linked list operations, that is, using double pointers, the moving speed is twice as fast. When the fast pointer reaches the end, the slower is the middle position.

The source code is as follows

ngx_queue_t *
ngx_queue_middle(ngx_queue_t *queue)
{
    ngx_queue_t  *middle, *next;

    middle = ngx_queue_head(queue);

    if (middle == ngx_queue_last(queue)) {
        return middle;
    }

    next = ngx_queue_head(queue);

    for ( ;; ) {
        middle = ngx_queue_next(middle);

        next = ngx_queue_next(next);

        if (next == ngx_queue_last(queue)) {
            return middle;
        }

        next = ngx_queue_next(next);

        if (next == ngx_queue_last(queue)) {
            return middle;
        }
    }
}

Of course, there are other operations, such as sorting, removing, and so on. It is basically the same as the regular doubly linked list operation.
It will not be described in detail here.

Guess you like

Origin blog.csdn.net/wangrenhaioylj/article/details/109708928