抛去所有的模块和各种定义的数据结构,对于一个没看过这么大工程的小白来说,太乱!乱的不要不要,光是各种数据结构的含义,就让我要抓狂了。好吧,我并不是说它结构不好,相反我感觉代码写的太棒了。。就是一时间。。接受不了。废话不说了,让烦恼开始吧,唉╮(╯▽╰)╭


第一点:ngx_cdecl

int ngx_cdecl main(int argc, char *const *argv);
  • 1
  • 1

是的,就是这个ngx_cdecl,之前知道在源码里面有__cdecl和__stdcall等东西,在这儿的ngx_cdecl又是什么,按理说是一样的,但是查到定义后是这样的:

#define ngx_cdecl
  • 1
  • 1

对,就是一个空的define,那它有啥用?当然有用,而且用得很好,要不怎么说人家是好代码呢,后路留的多好,避免以后填坑。nginx中使用这个宏是为了跨平台支持,方便调整函数调用方式。在遇到问题时,可以修改上面的定义为:

#define ngx_cdecl stdcal
  • 1
  • 1

要不怎么说多看代码有好处呢,这就是思想啊。好了再解释下cdecl和stdcall: 
__cdecl:C Declaration的缩写,表示C语言默认的函数调用方法:所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。被调用函数不会要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完全不同的参数都不会产生编译阶段的错误。 
调用函数的代码和被调函数必须采用相同的函数的调用约定,程序才能正常运行。 
__cdecl和__stdcall的区别:__cdecl是调用者清理参数占用的堆栈,__stdcall是被调函数清理参数占用的堆栈。假设函数A是__stdcall,函数B调用函数A。你必须通过函数声明告诉编译器,函数A是__stdcall。编译器自然会产生正确的调用代码。如果函数A是__stdcall,但在引用函数A的地方,你却告诉编译器,函数A是__cdecl方式,编译器产生__cdecl方式的代码,与函数A的调用约定不一致,就会发生错误。 
注意事项:由于__stdcall的被调函数在编译时就必须知道传入参数的准确数目(被调函数要清理堆栈),所以不能支持变参数函数,例如printf。而且如果调用者使用了不正确的参数数目,会导致堆栈错误。


第二点:ngx_int_t & ngx_uint_t

typedef intptr_t ngx_int_t;
typedef uintptr_t ngx_uint_t;
  • 1
  • 2
  • 1
  • 2

在stdint.h中找到intptr的定义:

    117 /* Types for `void *' pointers.  */  118 #if __WORDSIZE == 64  119 # ifndef __intptr_t_defined  120 typedef long int        intptr_t;  121 #  define __intptr_t_defined  122 # endif  123 typedef unsigned long int   uintptr_t;  124 #else  125 # ifndef __intptr_t_defined  126 typedef int         intptr_t;  127 #  define __intptr_t_defined  128 # endif  129 typedef unsigned int        uintptr_t;  130 #endif  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

定义中的注释说明,这两个类型是定义用来当作指针使用的,因为指针的长度和长整型一直是一样的,由于指针就是一个数组索引的存在,系统内核在操作内存时,就是将内存当做一个大数组,而指针就是数组索引/下标,内核程序员使用这种特殊的整型来接受内存地址值、操作内存相比使用指针更加直观,不容易犯错。 
intptr_t 这个类型可以被安全的在 void * 和 整数间转换,对于写跨 64 位平台的程序非常重要。也就是说,当你需要把指针作为一个整数来运算时,转换成 intptr_t 才是安全的,可以在运算完毕安全的转回指针类型,也避免了对指针解引用产生的bug。

由代码中的宏可以看出,intptr_t的长度是适应不同平台的,当编译环境是64位时,intptr_t是long int,否则就是int。

那么nginx中使用它来typedef出ngx_int_t是想要干吗?为啥不用int来? 
从类型名来看很容易理解为普通的int型,我想nginx使用它是因为intptr在定义的时候就自适应平台,根据平台来变化自己的长度,作者就不用自己再定义一次了。


第三点:ngx_log_t

 20 typedef struct ngx_log_s         ngx_log_t;45 typedef u_char *(*ngx_log_handler_pt) (ngx_log_t *log, u_char *buf, size_t len);46 typedef void (*ngx_log_writer_pt) (ngx_log_t *log, ngx_uint_t level,47     u_char *buf, size_t len);              // 看log.c中程序len的计算都是通过指针相减 48 49 50 struct ngx_log_s {51     ngx_uint_t           log_level; /*        日志级别,有define:0~8的值和对应的string数组*        cycle->log->log_level = NGX_LOG_INFO;*        if (log->log_level < level && !debug_connection) break;*        log->log_level |= d;*/52     ngx_open_file_t     *file;/*        日志文件,结构内有文件标志fd和文件名name*        n = ngx_write_fd(log->file->fd, errstr, p - errstr);*        if (log->file->fd == ngx_stderr) { wrote_stderr = 1;}*        log->file = ngx_conf_open_file(cycle, &error_log);*        if (new_log->file == NULL) { return NGX_CONF_ERROR;}*/53 54     ngx_atomic_uint_t    connection;/*        原子单元链接,定义为整形变量(与平台有关)*        if (log->connection) {p = ngx_slprintf(p, last, "*%uA ", log->connection);}*/55 56     time_t               disk_full_time;/*        写入full filesystem时间,代码中经常与ngx_time()比较*        if (ngx_time() == log->disk_full_time) {/** on FreeBSD writing to a full filesystem with enabled softupdates* may block process for much longer time than writing to non-full* filesystem, so we skip writing to a log for one second*/goto next;}*        if (n == -1 && ngx_errno == NGX_ENOSPC) {log->disk_full_time = ngx_time();}*/57 58     ngx_log_handler_pt   handler;/*        日志处理器,见45行定义*        if (level != NGX_LOG_DEBUG && log->handler) {p = log->handler(log, p, last - p);}*        cln->handler = ngx_log_memory_cleanup;*/59     void                *data;             /*        日志数据*        cln->data = new_log;*/60 61     ngx_log_writer_pt    writer;           /*        日志写入函数,见46行定义*        if (log->writer) {log->writer(log, level, errstr, p - errstr);goto next;}*/62     void                *wdata;            /* 日志内容/*        日志写入函数,见46行定义*        if (log->writer) {log->writer(log, level, errstr, p - errstr);goto next;}*/63 64     /*65      * we declare "action" as "char *" because the actions are usually66      * the static strings and in the "u_char *" case we have to override67      * their types all the time68      */69 70     char                *action;            /*       操作*       c->log->action = "waiting for request";*       c->log->action = "reading client request headers";*       c->log->action = "keepalive";*       log->action = "closing request";*       p = ngx_snprintf(buf, len, " while %s", log->action);*/          71 72     ngx_log_t           *next;73 };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105

为啥要先struct又在另一个头文件里typedef,因为现在用得是c,必须struct XXX来使用,所以typedef封装一下,让用户不知道它的具体结构。

nginx源码初读(1)--让烦恼从数据结构开始(ngx_cdecl/ngx_int/ngx_log)相关推荐

  1. nginx源码初读(8)--让烦恼从数据结构开始(ngx_event)

    nginx中的事件模块是一个很重要的模块,但这里作为初读,我们只简单看一下ngx_event的数据结构,至于模块和机制,留作之后再分析. 下面是结构体ngx_event_t的代码: typedef s ...

  2. 16w行的nginx源码,如何才能读懂呢?全面分析nginx的机制

    16w行的nginx源码,如何才能读懂呢?全面分析nginx的机制 1. nginx的轮子组成 2. nginx的epoll实现机制 3. nginx的内存机制 视频讲解如下,点击观看: 16w行的n ...

  3. 设计模式在C语言中的应用--读nginx源码

    市面上的"设计模式"书籍文章,皆针对Java/C++/C#等面向对象语言,似乎离开了面向对象的种种特性,设计模式就无法实现,没有用武之地了. 是这样吗?设计模式的概念是从建筑领域引 ...

  4. Nginx源码分析--数据对齐posix_memalign和memalign函数

    posix_memalign函数() /*  * 背景:  *      1)POSIX 1003.1d  *      2)POSIX 标明了通过malloc( ), calloc( ), 和 re ...

  5. Nginx源码分析:epoll事件处理模块概述

    nginx源码分析 nginx-1.11.1 参考书籍<深入理解nginx模块开发与架构解析> 事件处理模块概述 Nginx的高效请求的处理依赖于事件管理机制,本次默认的场景是Linux操 ...

  6. Nginx源码分析:惊群处理与负载均衡

    nginx源码分析 nginx-1.11.1 参考书籍<深入理解nginx模块开发与架构解析> Nginx的惊群处理与负载均衡概述 当Nginx工作在master/worker模式下时,就 ...

  7. Nginx源码分析:核心数据结构ngx_cycle_t与内存池概述

    nginx源码分析 nginx-1.11.1 参考书籍<深入理解nginx模块开发与架构解析> 核心数据结构与内存池概述 在Nginx中的核心数据结构就是ngx_cycle_t结构,在初始 ...

  8. Nginx源码分析:启动流程

    nginx源码分析 nginx-1.11.1 参考书籍<深入理解nginx模块开发与架构解析> nginx简介 Nginx的作为服务端软件,表现的主要特点是更快.高扩展.高可靠性.低内存消 ...

  9. nginx模块_使用gdb调试nginx源码

    工欲善其事必先利其器,如何使用调试工具gdb一步步调试nginx是了解nginx的重要手段. ps:本文的目标人群是像我这样初接触Unix编程的同学,如果有什么地方错误请指正. 熟悉gdb的使用 这里 ...

最新文章

  1. 【Netty】Netty为什么要手动释放ByteBuf资源?
  2. Leetcode 刷题笔记
  3. 转载、Python的编码处理(二)
  4. 一个div压在另一个div上面_【CSS小分享】用CSS画一个新拟态风格键盘
  5. 书评:使用Scikit-Learn和TensorFlow进行动手机器学习
  6. 化工计算机软件基础考试题,2013年化工工程师基础知识网友版真题(下午卷)...
  7. 【教程】PDF控件Spire.PDF 教程:在C#中检测PDF文件是否为PDF/A
  8. 2021蓝桥杯Java复习【史上最详细攻略】【持续更新】
  9. Java根据isbn查询图书信息_isbn书号查询api,根据图书ISBN查询详细信息
  10. springboot starter自定义实现公共模块
  11. 【转】基于gamebryo引擎开发过程中组件的应用和取舍 By 宋晓宇
  12. 数据管理DMS移动版之2018新年巨献
  13. 计算机网络近年的发展趋势,【网络技术论文】计算机网络技术发展趋势探析(共2622字)...
  14. freemind问题合集
  15. 人力资源和社会保障部——拟新增职业“密码技术应用员”
  16. 计算机网络知识详解之:TCP连接原理详解
  17. Python案例—掷骰子
  18. matlab模拟股票价格,matlab股票价格模拟
  19. 应届生找工作到哪里找
  20. 基于Ubuntu 操作系统如何卸载软件?

热门文章

  1. ADF_Tutorials系列17_ADF Faces_使用布局组件
  2. C#学习笔记(二)运算符 乘方 判断语句 循环语句 比较运算符 逻辑运算符 数组...
  3. 向模态窗体传递参数和获取返回值
  4. CodeForces - 1343F Restore the Permutation by Sorted Segments(思维)
  5. CodeForces - 1291D Irreducible Anagrams(思维+构造)
  6. CodeForces - 618D Hamiltonian Spanning Tree(思维+贪心)
  7. mvc登录设计的详细设计_产品设计:APP指纹密码登录设计
  8. html5伪类效果延缓,CSS3实现伪类hover离开时平滑过渡效果示例
  9. [USACO18JAN][luoguP4183 ]Cow at Large P
  10. (六)boost库之内存管理shared_ptr