nginx源码初读(1)--让烦恼从数据结构开始(ngx_cdecl/ngx_int/ngx_log)
来源:互联网 发布:中国钓鱼运动协会数据 编辑:程序博客网 时间:2024/06/15 04:14
抛去所有的模块和各种定义的数据结构,对于一个没看过这么大工程的小白来说,太乱!乱的不要不要,光是各种数据结构的含义,就让我要抓狂了。好吧,我并不是说它结构不好,相反我感觉代码写的太棒了。。就是一时间。。接受不了。废话不说了,让烦恼开始吧,唉╮(╯▽╰)╭
第一点:ngx_cdecl
- 1
是的,就是这个ngx_cdecl,之前知道在源码里面有__cdecl和__stdcall等东西,在这儿的ngx_cdecl又是什么,按理说是一样的,但是查到定义后是这样的:
- 1
对,就是一个空的define,那它有啥用?当然有用,而且用得很好,要不怎么说人家是好代码呢,后路留的多好,避免以后填坑。nginx中使用这个宏是为了跨平台支持,方便调整函数调用方式。在遇到问题时,可以修改上面的定义为:
- 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
- 1
- 2
在stdint.h中找到intptr的定义:
- 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
- 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)
- nginx源码初读(1)--让烦恼从数据结构开始(ngx_cdecl/ngx_int/ngx_log)
- nginx源码初读(1)--让烦恼从数据结构开始(ngx_cdecl/ngx_int/ngx_log)
- nginx源码初读(2)--让烦恼从数据结构开始(ngx_buf/ngx_chain)
- nginx源码初读(3)--让烦恼从数据结构开始(ngx_pool)
- nginx源码初读(4)--让烦恼从数据结构开始(ngx_str)
- nginx源码初读(5)--让烦恼从数据结构开始(ngx_array)
- nginx源码初读(6)--让烦恼从数据结构开始(ngx_list)
- nginx源码初读(7)--让烦恼从数据结构开始(ngx_queue)
- nginx源码初读(8)--让烦恼从数据结构开始(ngx_event)
- nginx源码初读(9)--让烦恼从数据结构开始(ngx_listening/ngx_connection)
- nginx源码初读(10)--让烦恼从数据结构开始(ngx_cycle)
- nginx源码初读(11)--让烦恼从数据结构开始(ngx_command/ngx_module/ngx_conf)
- nginx中的ngx_cdecl
- nginx源码剖析--从main函数开始
- nginx源码剖析(2)----从main()函数开始
- nginx源码剖析(2)----从main()函数开始
- mysql 让id重新从1开始
- 生存分析(3)
- 解决Tomcat7“At least one JAR was scanned for TLDs yet contained no TLDs”问题
- I2C设备、读写地址的关系
- Ubuntu Kylin安装Redis
- [JAVA] Spring封装JDBC
- nginx源码初读(1)--让烦恼从数据结构开始(ngx_cdecl/ngx_int/ngx_log)
- AS报错Error(303,27),找不到符号 方法 FloatMath.sin()
- Android NDK开发
- jMonkeyEngine之Camera全攻略
- 离群点(oulier)挖掘详解
- C#发送邮件(包含添加附件)
- 指针数组功能测试
- compilation terminated. In file included from <command-line>:0:0: /usr/include/stdc-predef.h:30:26:
- python requests 和正则表达式提取贴吧图片