• Nginx--单向链表分析


    1.基本数据结构

    1.1结点

    1. struct ngx_list_part_s {
    2. void *elts;
    3. ngx_uint_t nelts;
    4. ngx_list_part_t *next;
    5. };

    结构成员分析

    void* elts                         :数组元素指针

    ngx_uint_t                       :数组里面的元素数量

    ngx_list_part_t*             :下一个结点的指针

    它类似ngx_array_t,是一个简单的数组,也可以“泛型”存储数据,但少了一些成员,还有一个next指针指向链表里的下一个节点。

    1.2链表

    1. typedef struct {
    2. ngx_list_part_t *last;
    3. ngx_list_part_t part;
    4. size_t size;
    5. ngx_uint_t nalloc;
    6. ngx_pool_t *pool;
    7. } ngx_list_t;

    结构成员分析

    last:   链表的尾结点

    part:链表的头结点

    size:   链表储存元素的大小

    nalloc:每一个结点能够储存元素大小 

    pool : 使用的内存池

    对比 ngx_array_t可以看到,ngx_list_t 的成员size、nalloc和pool的含义是相同的,确定了节点里数组的元信息。可以这么说,链表里的每个节点就是一个简化的ngx_array_t数组结构

    ngx_list_t 的 part成员是链表的头节点(注意不是指针),part.next 指向链表里的第二个节点,而last则指向链表的尾节点。

    1.3图形解释


    2.操作函数

    static ngx_inline ngx_int_t
    ngx_list_init(ngx_list_t *list, ngx_pool_t *pool, ngx_uint_t n, size_t size)

    1. {
    2. list->part.elts = ngx_palloc(pool, n * size);
    3. if (list->part.elts == NULL) {
    4. return NGX_ERROR;
    5. }
    6. list->part.nelts = 0;
    7. list->part.next = NULL;
    8. list->last = &list->part;
    9. list->size = size;
    10. list->nalloc = n;
    11. list->pool = pool;
    12. return NGX_OK;
    13. }

    1. ngx_ok 是一个宏定义

    2.初始化确保list已经存在

    3.然后去初始化 第二个结点并且首尾相等

    ngx_list_t *
    ngx_list_create(ngx_pool_t *pool, ngx_uint_t n, size_t size)

     

    1. {
    2. ngx_list_t *list;
    3. list = ngx_palloc(pool, sizeof(ngx_list_t));
    4. if (list == NULL) {
    5. return NULL;
    6. }
    7. if (ngx_list_init(list, pool, n, size) != NGX_OK) {
    8. return NULL;
    9. }
    10. return list;
    11. }

    1. 分配内存

    2.init函数

    void *
    ngx_list_push(ngx_list_t *l)

    1. {
    2. void *elt;
    3. ngx_list_part_t *last;
    4. last = l->last;
    5. if (last->nelts == l->nalloc) {
    6. /* the last part is full, allocate a new list part */
    7. last = ngx_palloc(l->pool, sizeof(ngx_list_part_t));
    8. if (last == NULL) {
    9. return NULL;
    10. }
    11. last->elts = ngx_palloc(l->pool, l->nalloc * l->size);
    12. if (last->elts == NULL) {
    13. return NULL;
    14. l->last->next = last;
    15. l->last = last;
    16. }
    17. elt = (char *) last->elts + l->size * last->nelts;
    18. last->nelts++;
    19. return elt;
    20. }

    1.记住这是一个“添加元素” 后面有测试解释怎么填加

    2.是往尾结点上添加!!!

    3.     l->last->next = last;
            l->last = last; 

    改变尾结点

    4.  elt = (char *) last->elts + l->size * last->nelts;
        last->nelts++;

    类似与array数组!!!

     

    note 没有销毁操作!!!

    测试

    理解并掌握开源软件的最好方式莫过于自己写一些测试代码,或者改写软件本身,并进行调试来进一步理解开源软件的原理和设计方法。本节给出一个创建内存池并从中分配一个链表的简单例子。在该例中,链表的每个节点(part)可存放5个元素,每个元素4字节大小,创建链表后,要向链表添加15个整型元素。

    1. /**
    2. * ngx_list_t test, to test ngx_list_create, ngx_list_push
    3. */
    4. #include
    5. #include "ngx_config.h"
    6. #include "ngx_conf_file.h"
    7. #include "nginx.h"
    8. #include "ngx_core.h"
    9. #include "ngx_string.h"
    10. #include "ngx_palloc.h"
    11. #include "ngx_list.h"
    12. volatile ngx_cycle_t *ngx_cycle;
    13. void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
    14. const char *fmt, ...)
    15. {
    16. }
    17. void dump_pool(ngx_pool_t* pool)
    18. {
    19. while (pool)
    20. {
    21. printf("pool = 0x%x\n", pool);
    22. printf(" .d\n");
    23. printf(" .last = 0x%x\n", pool->d.last);
    24. printf(" .end = 0x%x\n", pool->d.end);
    25. printf(" .next = 0x%x\n", pool->d.next);
    26. printf(" .failed = %d\n", pool->d.failed);
    27. printf(" .max = %d\n", pool->max);
    28. printf(" .current = 0x%x\n", pool->current);
    29. printf(" .chain = 0x%x\n", pool->chain);
    30. printf(" .large = 0x%x\n", pool->large);
    31. printf(" .cleanup = 0x%x\n", pool->cleanup);
    32. printf(" .log = 0x%x\n", pool->log);
    33. printf("available pool memory = %d\n\n", pool->d.end - pool->d.last);
    34. pool = pool->d.next;
    35. }
    36. }
    37. void dump_list_part(ngx_list_t* list, ngx_list_part_t* part)
    38. {
    39. int *ptr = (int*)(part->elts);
    40. int loop = 0;
    41. printf(" .part = 0x%x\n", &(list->part));
    42. printf(" .elts = 0x%x ", part->elts);
    43. printf("(");
    44. for (; loop < list->nalloc - 1; loop++)
    45. {
    46. printf("0x%x, ", ptr[loop]);
    47. }
    48. printf("0x%x)\n", ptr[loop]);
    49. printf(" .nelts = %d\n", part->nelts);
    50. printf(" .next = 0x%x", part->next);
    51. if (part->next)
    52. printf(" -->\n");
    53. printf(" \n");
    54. }
    55. void dump_list(ngx_list_t* list)
    56. {
    57. if (list == NULL)
    58. return;
    59. printf("list = 0x%x\n", list);
    60. printf(" .last = 0x%x\n", list->last);
    61. printf(" .part = 0x%x\n", &(list->part));
    62. printf(" .size = %d\n", list->size);
    63. printf(" .nalloc = %d\n", list->nalloc);
    64. printf(" .pool = 0x%x\n\n", list->pool);
    65. printf("elements:\n");
    66. ngx_list_part_t *part = &(list->part);
    67. while (part)
    68. {
    69. dump_list_part(list, part);
    70. part = part->next;
    71. }
    72. printf("\n");
    73. }
    74. int main()
    75. {
    76. ngx_pool_t *pool;
    77. int i;
    78. printf("--------------------------------\n");
    79. printf("create a new pool:\n");
    80. printf("--------------------------------\n");
    81. pool = ngx_create_pool(1024, NULL);
    82. dump_pool(pool);
    83. printf("--------------------------------\n");
    84. printf("alloc an list from the pool:\n");
    85. printf("--------------------------------\n");
    86. ngx_list_t *list = ngx_list_create(pool, 5, sizeof(int));
    87. dump_pool(pool);
    88. for (i = 0; i < 15; i++)
    89. {
    90. int *ptr = ngx_list_push(list);
    91. *ptr = i + 1;
    92. }
    93. printf("--------------------------------\n");
    94. printf("the list information:\n");
    95. printf("--------------------------------\n");
    96. dump_list(list);
    97. printf("--------------------------------\n");
    98. printf("the pool at the end:\n");
    99. printf("--------------------------------\n");
    100. dump_pool(pool);
    101. ngx_destroy_pool(pool);
    102. return 0;
    103. }

    解析

    1.

    1. for (i = 0; i < 15; i++)
    2. {
    3. int *ptr = ngx_list_push(list);
    4. *ptr = i + 1;
    5. }

    这是通过给指针赋值来实现添加元素

    2.dump:(计算机内信息)转出,倾卸;转储;内容全部打印

    所以dump_loop是打印所有的pool等!!!

    结果

    1. # ./ngx_list_t_test
    2. -------------------------------- create a new pool:
    3. -------------------------------- pool = 0x9208020 .d .last = 0x9208048
    4. .end = 0x9208420
    5. .next = 0x0
    6. .failed = 0 .max = 984
    7. .current = 0x9208020
    8. .chain = 0x0
    9. .large = 0x0
    10. .cleanup = 0x0
    11. .log = 0x0 available pool memory = 984
    12. -------------------------------- alloc an list from the pool:
    13. -------------------------------- pool = 0x9208020 .d .last = 0x9208078
    14. .end = 0x9208420
    15. .next = 0x0
    16. .failed = 0 .max = 984
    17. .current = 0x9208020
    18. .chain = 0x0
    19. .large = 0x0
    20. .cleanup = 0x0
    21. .log = 0x0 available pool memory = 936
    22. -------------------------------- the list information:
    23. -------------------------------- list = 0x9208048 .last = 0x9208098
    24. .part = 0x920804c
    25. .size = 4
    26. .nalloc = 5
    27. .pool = 0x9208020
    28. elements: .part = 0x920804c .elts = 0x9208064 (0x1, 0x2, 0x3, 0x4, 0x5)
    29. .nelts = 5
    30. .next = 0x9208078 -->
    31. .part = 0x920804c .elts = 0x9208084 (0x6, 0x7, 0x8, 0x9, 0xa)
    32. .nelts = 5
    33. .next = 0x9208098 -->
    34. .part = 0x920804c .elts = 0x92080a4 (0xb, 0xc, 0xd, 0xe, 0xf)
    35. .nelts = 5
    36. .next = 0x0
    37. -------------------------------- the pool at the end:
    38. -------------------------------- pool = 0x9208020 .d .last = 0x92080b8
    39. .end = 0x9208420
    40. .next = 0x0
    41. .failed = 0 .max = 984
    42. .current = 0x9208020
    43. .chain = 0x0
    44. .large = 0x0
    45. .cleanup = 0x0
    46. .log = 0x0 available pool memory = 872
  • 相关阅读:
    CentOS 7 上安装 Oracle 11g 数据库
    【云原生 | Docker 高级篇】03、搭建 Redis 3主3从集群
    笔记:Python 循环结构练习题
    机器学习之算法优化(二)
    好消息!PMP项目管理证书列入急需紧缺专业人才人员
    全网最全超详细.htaccess语法讲解
    浅谈AVL树
    4-4网络层-IPv6
    iptables DNAT和de-DNAT
    动态规划专栏
  • 原文地址:https://blog.csdn.net/qq_62309585/article/details/128049308