存档

‘Nginx’ 分类的存档

nginx进程管理-signaller进程

2020年5月25日 评论已被关闭
nginx控制进程用来控制master进程,我们知道nginx有四种类型:
位于:src/os/unix/ngx_process_cycle.h

当我们要对nginx升级、重启、切割等待日志时,这是nginx的角色为NGX_PROCESS_SIGNALLER

也就是说在我们使用nginx -s 信号时这时启动的nginx属于NGX_PROCESS_SIGNALLER类型了,做为signaller的nginx它的作用是对master的管理,信号类型存储在ngx_signal这个变量里,它的用法是这样的:

当程序启动时我们指定了合法的-s参数时,ngx_process被设置成了NGX_PROCESS_SIGNALLER,接下来的初始化函数ngx_init_cycle中,识别了NGX_PROCESS_SIGNALLER这个类型会把创建pid,创建文件,打开端口等等这些全部忽略,只调用了解析配置和各个模块的初始化配置的回调函数,所以我们在写core模块时一定要注意不要在ini_conf回调函数打开资源。

我们可以看到在初始化时如果是信号进程会跳过一些系申请统资源之类的操作,同时也会初始化最外层的core模块的配置。在所有配置解析并初始化完成后,信号进程开始给master发送指令了,这过程就是读取配置后的pid文件里的进程ID,然后通过进程ID给master进行发送信号了。

如果只是发送信号,从代码里了解到下面是等价的:(假设master的进程号是12345)

至于为什么要用这些信号呢或者大家可以思考一下,这两种方法的利弊在什么地方。

分类: C/C++, Linux, Nginx 标签:

Nginx使用instance标记处理kqueue/epoll中的stale事件

2015年8月28日 评论已被关闭

下面以epoll为例:

每个fd往往会关联一个自定义的结构体来表示逻辑上的连接。比如在nginx中每个ngx_connection_t都抽象成一个TCP连接并且与fd关联。

当我们accept到一个连接的时候,我们会申请这样一个ngx_connection_t,随后将这个fd与ngx_connection_t关联并加入到epoll循环。

代码(添加读事件)

然后我们使用epoll_wait来检查发生的事件

每个epoll_event的data.ptr是由ngx_connection_t*指针与instance相或而来,也就是data.ptr = c | instance;这样做是有前提条件的,那就是c必须是偶数,因为instance是bool类型,data.ptr最末位存储了instance的值。

 

假设当某一次epoll_wait后返回了一组epoll_event。

随后进行了如下操作:如图1所示:

(1)fd=47的文件描述有事件发生。

(2)处理fd=47时,我们关闭了fd=12的连接,回收了ngx_connection_t内存。

(3)接着处理fd=12时,此时data_ptr指向的ngx_connection_t已经被销毁,访问data_ptr将出现致命错误。

20150828160701

解决方法(如图2所示):暂不回收ngx_connection_t内存而是将ngx_connection_t的fd设置为-1,那么处理fd=12时,发现ngx_connection_t中的fd=-1,那么足以证明这个fd在之前已经被释放掉了,从面阻止使用data_ptr继续使用,这就是stale事件。

20150828160702

 

当我们将fd=12的ngx_connection_t回收后将fd设成了-1,防止处理到fd=12时使用了被释放的data_ptr。

试想一下,此时将fd设置成了-1,但在处理fd=12前,我将刚才释放的ngx_connection_t重新分配给了新连接fd=48(调用了accept()),那么在处理fd=12时,其data_ptr仍然不能使用,因这个ngx_connection_t已不属于fd=12而是属于fd=48,也就是说fd=12的ngx_connection_t已被释放并被fd=48使用。

我们使用instance来区分这个ngx_connection_t到底属于谁。因为本身data_ptr中存储了instance值,并且ngx_connection_t中也存储了instance值,在申请ngx_connection_t时,我们要将ngx_connection_t中的instance值置反。当ngx_connection_t的instance与data_ptr不一致时,说明当前fd已销毁。(如图3所示)

20150828160703

 

注意

另外,有一点要说明的是,如果在处理fd=12之前,fd=48也被销毁了,然后该ngx_connection_t又被fd=49复用,那么这种情况仍然会有问题。

这会导致data_ptr中的instance值与ngx_connection_t一致(两次置反)并且fd=49。event_list原本指示的fd=12有事件,但被nginx错误地认为了fd=49有事件发生,目前我还没想到好的解决办法。

分类: C/C++, Linux, Nginx 标签:

nginx的模块上下文

2015年4月26日 评论已被关闭

ngx_modules数组定义:

初始化完成: 阅读全文…

分类: Nginx 标签:

nginx中定时器与事件流程

2015年4月13日 评论已被关闭

1.nginx中的时间更新

Nginx在内部自己缓存时间,那么这些时间值在什么地方更新呢?

1.1 收到信号时更新时间

1.2 timer_resolution值为0

如果用户没有设置timer_resolution值或者设置为0值,那么每次在轮询事件都会设置NGX_UPDATE_TIME标志,表示轮询结束后要更新时间(以kqueue为例):

轮询时:

1.3 timer_resolution值非0

如果用户设置timer_resolution为非零值,nginx会在定时器触发时更新时间。

在nginx中系统定时器的具体实现有两种,一种是使用setitimer(),另外一种具体事件中模型实现的。

1.3.1使用setitimer()

在事件初始化后使用setitimer(timer_resolution),那么系统会每隔timer_resolution(单位为毫秒)发送SIGALARM信号,信号处理函数:

后续的的轮询会被打断并在结束后会去判断ngx_event_timer_alarm值,如果为1的话会更新时间(以kqueue为例):

1.3.2使用特定的事件模型

对于特定的事件模型,在这里只包括kqueue和eventport。它们内部实现了一个定时器,我们在事件初始化时安装定时器,例如(以kqueue为例):

同时设置还会置上NGX_USE_TIMER_EVENT标志,并且定时器触发时没有回调函数,我们要在事件轮询后判断是否是定时器事件,如果是则要更新时间(以kqueue为例):

 

总结:nginx自身缓存时间。 阅读全文…

分类: Linux, Nginx 标签:

Nginx源码分析(一)

2012年3月12日 没有评论

1.错误定义

分析源码从最简单的地方入手,首先来看nginx的错误码定义,代码在ngx_errno.h,ngx_errno.h文件中。一共就两个函数。

  1. u_char *ngx_strerror(ngx_err_t err, u_char *errstr, size_t size);
  2. ngx_uint_t ngx_strerror_init(void);

系统启动时会初始化全局变量ngx_sys_errlist,这是一个全局ngx_str_t数组,数组大小为NGX_SYS_NERR,每个元素都一个结构体为:

  1. typedef struct {
  2.     size_t      len;//data成员的大小
  3.     u_char     *data;//一个字符串
  4. } ngx_str_t;

初始化:ngx_uint_t ngx_strerror_init
所以初始化的函数是填充每一个元素,该元素的数组下标即为错误码,元素len成员是指元素data字符串的大小,data是该错误码(数组下标)的文字描述,通过函数strerror(err)来取得错误码的信息串。
获取错误码对应的信息串:ngx_strerror
在ngx_sys_errlist找到err对应位置的错误信息,如果错误码不在数组下标范围则返回未知错误,同时检查传入的长度,太小于将会截断错误信息串。

分类: Linux, Nginx 标签:

在windwos下的编译Nginx

2012年2月28日 没有评论

在windows下编译nginx可以利用VC编译来调试nginx,当我们很熟悉了操作系统上层的实现之后转向分析nginx代码也方便一些。
在windows下编译nginx跟在Linux下的步骤差不多。利用svn工具下载源码,第三方网站下载的tar文件中没有win32的配置文件;由于configure文件是sh脚本,所以只能用第三方仿真软件,我这里用的是MinGW Shell;配置完成后就是编译,只要调用VC的编译工具cl.exe编译就行了。

下载工具
需要的工具有:
1.TortoiseSVN:http://downloads.sourceforge.net/project/tortoisesvn/1.7.5/Application/TortoiseSVN-1.7.5.22551-win32-svn-1.7.3.msi
2.MinGW32:http://10.10.4.6/download/7377061/8602355/3/exe/230/40/1322227850470_40/mingw-get-inst-20111118.exe
3.VC2010 express:http://download.microsoft.com/download/e/5/e/e5e362e1-6a2a-4ce3-bbac-659c9740ab04/vc_web.exe
上面的工具下载安装完成即可。

下载源码
源码地址在:svn://svn.nginx.org/nginx/trunk 使用svn将源码检出到本地任意目录,比如f:\nginx\trunk
目录结构如下:
f—nginx—trunk—(auto conf contrib docs misc src)

配置代码环境
打开cmd命令行提示:

2.设置VC的环境变量:在命令提示符中键入命令(根据VC的安装目录不同而不同,x86为参数)

设置MinGW:在命令提示符键入命令(根据MinGW32安装目录不同而不同):

检查环境:
弹出MinGW窗口,关闭其它的cmd窗口。在MinGW32的窗口输入:

有如下显示:
用于 80×86 的 Microsoft (R) 32 位 C/C++ 优化编译器 16.00.30319.01 版
版权所有(C) Microsoft Corporation。保留所有权利。
用法: cl [ 选项… ] 文件名… [ /link 链接选项… ]
说明编译环境配置成功
编译
cd进入主目录,即truck目录

配置:

注解:
–prefix=. 表示安装目录在本目录下
–with-cc-opt=”-D FD_SETSIZE=4096″ 预定义宏FD_SETSIZE大小4096
–without-http_rewrite_module 不加载rewite模块
–without-http_gzip_module 不加载gzip模块
–with-cc=cl 编译器为cl
编译:

在obj/目录下为生成的中间文件和nginx.exe文件。

分类: Nginx 标签: