Nginx-0.1.0源码学习
文章平均质量分 79
oyw5201314ck
这个作者很懒,什么都没留下…
展开
-
1.Nginx修改进程名称
我们在通过ps -ef | grep nginx 查看Nginx的进程时,会发现显示的名称有些与众不同,如下所示root@test:/home/test# ps -ef | grep nginxroot 2047 1 0 01:58 ? 00:00:00 nginx: master process /usr/sbin/nginx -c /etc/ngin原创 2017-10-17 17:21:04 · 3515 阅读 · 0 评论 -
6.Nginx红黑树rbtree
Nginx的定时器管理借助红黑树来完成,红黑树这种数据结构在很多开源项目中被广泛使用。红黑树是一种自平衡二叉搜索树,可以在O(log n)时间内做查找、插入和删除,这里n是树中元素的数目。红黑树是每个节点都带有颜色属性的二叉搜索数,颜色为红色或黑色。在二叉搜索树的一般要求以外,它还有以下的额外要求:(1)节点是红色或黑色(2)根节点是黑色的(3)所有叶子都是黑色(叶子是原创 2017-10-24 14:55:39 · 801 阅读 · 0 评论 -
16.Nginx解析配置文件之ngx_conf_parse
上一篇讲的ngx_conf_read_token用于从配置文件内容中提取token,通常在一个配置行结束或者一个配置块开始时返回。提取了这些token后,我们还需要找到对应的选项并且进行赋值,这就是ngx_conf_parse的作用。/* core/ngx_conf_file.c *//* The ten fixed arguments */static int argume原创 2017-11-03 09:39:36 · 1660 阅读 · 0 评论 -
7.Nginx内存池
如果我们在需要的时候才分配内存,使用完毕就释放,这种内存管理方式比较简单粗暴,但是会带来内存碎片的问题从而降低性能;为了避免上述弊端,Nginx使用内存池来进行内存管理。预先申请一个或多个内存块,然后真正使用内存之时,从这些内存块分配空闲区间; 当内存块耗尽时,再次申请新的内存块。当然内存池也是有其他弊端的,假设在内存池中存放了3个对象A/B/C,这3个对象的生命周期不一致,C是最后使用完毕的原创 2017-10-26 09:42:24 · 279 阅读 · 0 评论 -
32.Nginx HTTP之ngx_http_handler函数
前面我们看到,在HTTP 0.9中处理完请求行后; 在HTTP>=1.0中处理完请求头后,Nginx会调用ngx_http_handler函数对请求进行处理。/* http/ngx_http_core_module.c *//* HTTP的phase事件处理函数 * param ev: 待处理的事件 */static void ngx_http_phase_event_han原创 2017-11-17 10:28:08 · 876 阅读 · 0 评论 -
8.Nginx数据结构之数组Array
在core目录下,可以发现Nginx其实自己实现了很多基本的数据结构,本篇会对数组Array进行学习。/* ngx_core.h */typedef struct ngx_array_s ngx_array_t;/* ngx_palloc.h */// 将alloc赋值给p, 如果p等于NULL, 那么返回rc#define ngx_test原创 2017-10-26 14:44:29 · 438 阅读 · 0 评论 -
9.Nginx数据结构之链表List
上一篇我们学习了Nginx的数组结构,这一篇学习链表结构List,链表和数组最大的不同在于,数组元素是存放在一块连续内存空间内的,链表则没有这个限制,链表的各个元素或者节点的存放是随机零散的。这两种结构的特性导致了它们各自的优缺点,我们需要根据应用场景进行灵活选择:1.数组是顺序存储的,那么我们可以通过下标快速访问数组中任何元素, 也就是随机访问效率低; 但是我们在做插入和删除元素的操作时,需原创 2017-10-26 16:30:19 · 421 阅读 · 0 评论 -
25.Nginx之HTTP入口
学习了前面的一些代码,我们大概知道了Nginx的进程模型与事件处理模型,但是Nginx是著名的HTTP服务器,而我们目前好像并未学习到任何与HTTP相关的代码,那么Nginx究竟是怎么使用HTTP的各个模块的呢?前面我们学习了Nginx的启动流程之ngx_init_cycle这个环节,而里面涉及到配置文件解析的内容,代码如下所示。从这个代码片段,我们可以发现: Nginx的配置文件解析原创 2017-11-14 16:56:22 · 1358 阅读 · 0 评论 -
17.Nginx事件循环之定时器处理
Nginx支持不同平台下的高性能事件处理模型,例如Linux下的epoll、FreeBSD下的kqueue等,而我们的学习依旧针对Linux进行。接下来要说的是Nginx的事件循环,与很多网络库类似,在主事件循环中的第一步就是对定时器进行处理。/* core/ngx_time.c */ngx_epoch_msec_t ngx_elapsed_msec; // 用于记录N原创 2017-11-06 10:51:53 · 436 阅读 · 0 评论 -
26.Nginx HTTP之ngx_http_block
上一篇提到ngx_http_block(或者说http块指令)是Nginx中HTTP模块的入口,这一篇学习下ngx_http_block这个指令回调中做了哪些工作。从以下代码中,我们可以看出,ngx_http_block主要做了如下工作:1. 创建HTTP配置上下文2.对http指令块进行配置解析3.初始化HTTP各处理阶段4.对HTTP监听的端口、地址、虚拟主机名称进行合并整原创 2017-11-15 11:51:24 · 1136 阅读 · 0 评论 -
24.Nginx监听套接字读事件处理函数ngx_event_accept
前面讲过ngx_event_core_module模块的init_process函数ngx_event_process_init会为每个监听套接字的读事件注册处理函数ngx_event_accept,本篇就学习一下在ngx_event_accept函数中到底进行了哪些工作。/* event/ngx_event_accept.c *//* 监听套接字的读事件处理函数 * param原创 2017-11-09 17:17:48 · 1730 阅读 · 0 评论 -
27.Nginx HTTP之监听套接字连接处理函数ngx_http_init_connection
前一篇讲过,对于HTTP指令块下的server,Nginx会为其创建相应的监听套接字,并且注册连接处理函数ngx_http_init_connection。我们在ngx_event_accept中看到过,该函数会在accept后进行调用。/* http/ngx_http_request.h */typedef struct {原创 2017-11-15 17:30:14 · 1136 阅读 · 0 评论 -
29.Nginx HTTP之请求行解析函数ngx_http_parse_request_line
Nginx的HTTP模块中使用ngx_http_parse_request_line函数来对读取的请求行进行解析,HTTP请求行的格式不是很复杂,但是要注意HTTP 0.9与1.0、1.1之间的区别;另外,作为Nginx的第一个版本,里面支持的请求方法也只有GET、POST和HEAD。/* http/ngx_http_parse.c *//* 解析HTTP请求行 * param原创 2017-11-16 14:28:59 · 1746 阅读 · 1 评论 -
28.Nginx HTTP之读取处理请求行函数ngx_http_process_request_line
前面我们看到,Nginx会在适当的时机(启用HTTPS时那就是在SSL握手之后)为HTTP连接的读事件注册处理函数ngx_http_process_request_line,该函数用于读取并处理HTTP请求行。HTTP请求行格式为: [请求方法][空格][URL][空格][协议版本][回车符][换行符]一般来说,HTTP请求行不会很长,但是依旧有可能在单次系统调用中无法读取完整的请求行,所原创 2017-11-15 18:29:18 · 553 阅读 · 0 评论 -
31.Nginx HTTP之请求头解析函数ngx_http_parse_header_line
HTTP >= 1.0 的版本中,请求行后紧跟的就是请求头了,Nginx使用ngx_http_parse_header_line来对请求头进行解析。/* 解析HTTP请求头 * param r: 待处理的HTTP请求r * b: 存放请求头的缓冲区 * return : 解析完请求头的一行时返回NGX_OK; * 解析完整个请求头时返回NGX_HT原创 2017-11-16 18:34:52 · 2799 阅读 · 0 评论 -
15.Nginx解析配置文件之ngx_conf_read_token
Nginx的可配置选项非常的多, 意味着配置文件可以相当复杂,那么解析起来也是困难重重,今天学习一下与配置解析有关的函数ngx_conf_read_token;顾名思义,可以看出这是一个用于从配置文件中提取token的函数, 什么是token呢?举栗子,下面这个配置片段中,user是一个token,www-data是一个token,worker_processes、auto、pid、/ru原创 2017-11-02 15:11:44 · 979 阅读 · 0 评论 -
11.Nginx启动流程之ngx_add_inherited_sockets
Nginx的启动流程在ngx_os_init后,会调用ngx_add_inherited_sockets对继承的套接字描述符进行处理,下面对这个步骤进行代码分析:/* core/ngx_string.c *//* 将一串由数字组成的十进制字符串转换为整数 param line: 字符串的首地址 n: 字符串长度*/ngx_int_t ngx_ato原创 2017-10-30 16:24:32 · 1304 阅读 · 0 评论 -
2.Nginx切换为守护进程
Nginx配置为以守护进程的方式运行时,在主函数里面会通过调用ngx_daemon来使自己切换为守护进程,具体配置项为"daemon on/off".如果阅读过其他的服务端代码例如memcached,会发现这些程序切换为守护进程的方式基本是一致的,大致遵循如下几个步骤:1.调用fork来创建一个子进程,并使父进程终止,然后子进程自动转化为守护进程2.调用setsid来创建新会话,并使子原创 2017-10-18 17:13:50 · 2649 阅读 · 0 评论 -
10.Nginx启动流程之ngx_os_init
Nginx在启动流程中会调用ngx_os_init来初始化一些与操作系统有关的全局变量,不同操作系统下ngx_os_init的实现不同,在os/unix下我们看到Nginx为linux、freebsd、solaris等操作系统实现了对应的ngx_os_init函数。下面以linux操作系统进行讲解:原创 2017-10-26 18:43:07 · 1123 阅读 · 0 评论 -
3.Nginx信号控制
Nginx可以以master-worker的进程模型运行,master进程负责对worker进程管理;Nginx也允许我们通过信号来控制master进程,譬如当我们修改配置文件后,我们可以向master进程发送特定信号使Nginx平滑重启,来此达到不影响现有连接的目的。从ngx_master_process_cycle函数中,我们可以看出Nginx允许用户通过以下几种信号进行控制,Ng原创 2017-10-18 17:45:46 · 439 阅读 · 0 评论 -
4.Nginx创建worker进程
Nginx master进程在进入自己的主循环前,会创建worker进程,默认的worker进程数量为1,我们可以根据服务器的cpu核数来配置worker数量,以充分利用多核资源,或者配置worker_processes为auto来让Nginx自动进行检测。原创 2017-10-19 17:35:06 · 1136 阅读 · 0 评论 -
5.Nginx进程通信
在4中我们看到了,Nginx的master进程在创建worker进程时也会创建一个流管道(Unix域字节流socketpair),然后master进程和worker进程之间的通信就借助这个流管道来进行。在Nginx中,把这个流管道称之为channel,相关的发送接收消息函数在nginx_channel.c源文件中。结合4和下面的代码学习,我们可以看出Nginx的worker进程也可以借助上面的原创 2017-10-20 10:48:34 · 455 阅读 · 0 评论 -
18.Nginx事件循环之事件处理
前面学习了Nginx事件循环的前半部分:定时器处理,接下来就该学习后半部分:事件处理了。Nginx使用一个连接池来处理所有的连接,每个连接对应一个文件描述符,所有监听套接字也会各占用一个连接,每个连接包含2个事件:读和写。/* event/ngx_event.c */ngx_int_t ngx_accept_disabled;原创 2017-11-07 15:42:37 · 472 阅读 · 0 评论 -
19.Nginx原子操作
Nginx定义了自己的原子类型,并实现了部分原子操作,从代码中我们可以看出,原子操作的关键在于lock汇编指令前缀(锁内存总线)。从前面的代码学习,我们可以发现Nginx的worker进程间accept互斥锁是借助于下面的原子操作ngx_atomic_cmp_set来实现的/*os/unix/ngx_atomic.h *//* __i386__和__amd64__是编译器的预定义宏, 用于表示...原创 2017-11-08 10:22:29 · 644 阅读 · 0 评论 -
20.Nginx自旋锁
对于我们通常使用的阻塞锁,当进程尝试获取锁但是锁又被占用时,那么进程就会进入阻塞状态,并让出处理器。这在大多数情况下都是很有效的,但是在多核且内核允许抢占的情况下,假设锁被占用的时间很短,甚至比内核进行进程调度的开销时间还短,那么此时被阻塞是得不偿失的;相反,我们不停轮询锁的状态,并在锁没有被占用的时候尝试获取,这种方式反而更高效一些。这就是本次要学习的“自旋锁“,对于Nginx这种极致追原创 2017-11-08 11:22:58 · 456 阅读 · 0 评论 -
21.Nginx工作进程之处理函数
前面我们学习了Nginx事件循环的内容,其实就是为此篇学习worker进程的处理函数做铺垫的。/* os/unix/ngx_channel.c *//* 将通道的读/写事件添加到事件循环, 并注册相应的事件发生处理函数 * param cycle: ngx_cycle_t指针 * fd: 通道任意一侧的文件描述符 * event: 读/写事原创 2017-11-08 16:44:18 · 381 阅读 · 0 评论 -
22.Nginx模块
看Nginx代码时, src目录下的结构为core、event、http和os,可见Nginx的代码层次十分清晰;同样,我们在代码中也经常看到ngx_modules这个全局变量,可见在Nginx中是有模块概念的,事实上Nginx的设计就是高度模块化的,这一节我们学习下Nginx的模块结构体和ngx_modules数组。/* core/ngx_core.h */typedef str原创 2017-11-08 17:15:30 · 4876 阅读 · 2 评论 -
23.ngx_event_core_module模块之ngx_event_process_init
学习了上一篇worker进程处理函数的代码,有很多细节我们还没掌握,首先,Nginx是怎么接收连接的?前面我们的确是看到了创建监听套接字这些操作,但是这些监听套接字的读事件是怎么添加进事件处理模型的呢?这就是本篇学习的内容,如上一篇中所学,worker进程在进入主循环之前,会调用Nginx各个模块的init_process函数,而ngx_event_core_module模块的init_proce原创 2017-11-09 09:40:58 · 629 阅读 · 0 评论 -
14.Nginx数据结构之缓冲区链表Chain
上一篇我们学习了Nginx的缓冲区数据结构buf,这一篇学习的缓冲区链表Chain,其各个节点的数据区指向的就是buf。/* core/ngx_buf.h */typedef struct ngx_chain_s ngx_chain_t;struct ngx_chain_s { // 缓冲区链表节点结构体定义 ngx_buf_t原创 2017-10-31 17:50:40 · 530 阅读 · 0 评论 -
13.Nginx数据结构之缓冲区Buf
Nginx的缓冲区数据结构,代表一些具体的数据,这些数据既可以在内存中,也可以在文件中,或者两者兼备。/* core/ngx_buf.h */typedef void * ngx_buf_tag_t;typedef struct ngx_buf_s ngx_buf_t;struct ngx_buf_s { // 缓冲区结构体定...原创 2017-10-31 16:59:48 · 317 阅读 · 0 评论 -
12.Nginx启动流程之ngx_init_cycle
Nginx的启动流程在ngx_add_inherited_sockets之后,会调用ngx_init_cycle来创建cycle,从下面的代码分析,我们可以看出,在ngx_init_cycle中,Nginx主要进行了以下工作:1.根据旧cycle来创建新cycle,根据旧cycle的经验,可以推测出创建新cycle所需要的内存空间2.对新cycle进行初始化工作,包括打开文件、打开监听套接原创 2017-10-31 10:26:24 · 818 阅读 · 0 评论 -
30.Nginx HTTP之读取处理请求头函数ngx_http_process_request_headers
在HTTP >= 1.0的版本中,读取处理完HTTP请求行后,紧接着就应该是读取处理HTTP请求头了,Nginx使用ngx_http_process_request_headers来完成这个工作。/* http/ngx_http_request.c *//* 处理HTTP请求头 * param r: 待处理的HTTP请求 * return : */static ngx_i原创 2017-11-16 17:21:50 · 1946 阅读 · 0 评论