nginx源码分析—处理继承的sockets
来源:互联网 发布:淘宝服务站加盟 编辑:程序博客网 时间:2024/05/18 15:25
Content
- 序
- 侦听结构
- ngx_add_inherited_sockets()分析
- ngx_set_inherited_sockets()分析
- 小结
1.序
源代码:
//通过环境变量NGINX完成socket的继承,继承来的socket将会放到init_cycle的listening数组中。//在NGINX环境变量中,每个socket中间用冒号或分号隔开。完成继承同时设置全局变量ngx_inherited为1 if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) { return 1; }
2.侦听结构
侦听结构较为复杂,描述如下。
file: ./src/core/ngx_connection.h
typedef struct ngx_listening_s ngx_listening_t;struct ngx_listening_s { ngx_socket_t fd;/*?文件描述符,即socket?*/ struct sockaddr *sockaddr;/*?socket地址?*/ socklen_t socklen; /* size of sockaddr */ size_t addr_text_max_len; ngx_str_t addr_text; int type; int backlog; int rcvbuf;/*?接收缓冲区?*/ int sndbuf;/*?发送缓冲区?*/#if (NGX_HAVE_KEEPALIVE_TUNABLE) int keepidle; int keepintvl; int keepcnt;#endif /* handler of accepted connection */ ngx_connection_handler_pt handler; void *servers; /* array of ngx_http_in_addr_t, for example */ ngx_log_t log; ngx_log_t *logp; size_t pool_size; /* should be here because of the AcceptEx() preread */ size_t post_accept_buffer_size; /* should be here because of the deferred accept */ ngx_msec_t post_accept_timeout; ngx_listening_t *previous;/*?指向前一个ngx_listening_t结构?*/ ngx_connection_t *connection; ngx_uint_t worker; unsigned open:1; unsigned remain:1; unsigned ignore:1; unsigned bound:1; /* already bound */ unsigned inherited:1; /* inherited from previous process */ unsigned nonblocking_accept:1; unsigned listen:1; unsigned nonblocking:1; unsigned shared:1; /* shared between threads or processes */ unsigned addr_ntop:1;#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) unsigned ipv6only:1;#endif#if (NGX_HAVE_REUSEPORT) unsigned reuseport:1; unsigned add_reuseport:1;#endif unsigned keepalive:2;#if (NGX_HAVE_DEFERRED_ACCEPT) unsigned deferred_accept:1; unsigned delete_deferred:1; unsigned add_deferred:1;#ifdef SO_ACCEPTFILTER char *accept_filter;#endif#endif#if (NGX_HAVE_SETFIB) int setfib;#endif#if (NGX_HAVE_TCP_FASTOPEN) int fastopen;#endif};
sizeof(ngx_listening_t)=184。结构如下图。
ngx_listening_t与ngx_connection_t之间的关系如下图。
2. ngx_add_inherited_sockets()分析
该函数通过解析环境变量NGINX_VAR=”NGINX”,将其中的 socket number 保存至 ngx_cycle.listening 数组,该数组元素类型为ngx_listening_t。这些socekts在环境变量中以’:’或’;’隔开。
例如,为调试方便,设环境变量NGINX为如下值
export NGINX=”16000:16500:16600;”
注意:当然,后续的测试并不一定会成功,此处只是为了分析该函数。例如,可能会出现如下错误。
nginx: [crit] getsockname() of the inherited socket #16000 failed (9: Bad file descriptor)
nginx: [crit] getsockname() of the inherited socket #16500 failed (9: Bad file descriptor)
nginx: [crit] getsockname() of the inherited socket #16600 failed (9: Bad file descriptor)
/*?传入该参数的是init_cycle,调用ngx_init_cycle()后全局变量ngx_cycle会指向该结构*/static ngx_int_tngx_add_inherited_sockets(ngx_cycle_t *cycle){ u_char *p, *v, *inherited; ngx_int_t s; ngx_listening_t *ls; inherited = (u_char *) getenv(NGINX_VAR);//从环境中取字符串,获取环境变量的值 if (inherited == NULL) { return NGX_OK; } ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "using inherited sockets from \"%s\"", inherited); if (ngx_array_init(&cycle->listening, cycle->pool, 10, sizeof(ngx_listening_t)) != NGX_OK)/*?初始化ngx_cycle.listening数组,?10个元素空间?*/ { return NGX_ERROR; } for (p = inherited, v = p; *p; p++) { if (*p == ':' || *p == ';') { s = ngx_atoi(v, p - v);/*?sockets是10进制正整数?*/ if (s == NGX_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "invalid socket number \"%s\" in " NGINX_VAR " environment variable, ignoring the rest" " of the variable", v); break; } /*第一次满足该条件时v和p分别指向如下值,此时解析出s=16000 (gdb) p v $6 = (u_char *) 0x6b0139 "16000:16500:16600;" (gdb) p p $7 = (u_char *) 0x6b013e ":16500:16600;" */ v = p + 1; ls = ngx_array_push(&cycle->listening);/*?将合法的socket?number加入该数组*/ if (ls == NULL) { return NGX_ERROR; } ngx_memzero(ls, sizeof(ngx_listening_t)); ls->fd = (ngx_socket_t) s; } } ngx_inherited = 1; return ngx_set_inherited_sockets(cycle);/*?该函数逐一设置cycle->listening数组每个元素?*/}
调试过程中,得到以下信息,供参考。
(gdb) p cycle->listening$11 = {elts = 0x6b02a0, nelts = 3, size = 184, nalloc = 10, pool = 0x6af650}(gdb) x/w 0x6b02a00x6b02a0: 16000(gdb) x/w 0x6b03580x6b0358: 16500(gdb) x/w 0x6b04100x6b0410: 16600
可以验证,0x6b0358-0x6b02a0=0xB8=184,0x6b0410-0x6b0358=0xB8=184。
3. ngx_set_inherited_sockets()分析
该函数从参数cycle(后续调用ngx_init_cycle()函数后全局变量ngx_cycle会指向该参数)的listening数组中逐一对每个元素(ngx_listening_t结构)进行初始化,即初始化除fd字段外的其他的字段。
因此,ngx_set_inherited_sockets()函数主要完成以下事情。
对全局变量ngx_cycle的listening数组,逐一设置该数组每个元素的以下字段
ls[i].sockaddr (调用getsockname())ls[i].addr_text_max_lenls[i].addr_textls[i].backlogls[i].rcvbuf (调用getsockopt())ls[i].sndbuf (调用getsockopt())ls[i].accept_filterls[i].deferred_accept
涉及到的相关系统函数调用如下。
getenv()获取环境变量,并返回指向该值字符串的指针;getsockname()获取socket名字(地址及长度);getsockopt()获取socket选项;
- nginx源码分析—处理继承的sockets
- nginx源码分析—处理继承的sockets
- nginx源码分析—处理继承的sockets
- nginx源码分析—处理继承的sockets
- nginx 源码学习笔记(十八)—— ngx_add_inherited_sockets 继承的sockets
- nginx 源码学习笔记(十八)—— ngx_add_inherited_sockets 继承的sockets
- Nginx源码分析——日志处理
- nginx源码分析--配置信息的继承&合并
- Nginx源码分析—nginx的配置
- Nginx源码分析--字符串处理
- nginx源码分析(7)——请求处理
- nginx源码分析(8)——phase handler处理
- Nginx源码分析—过期事件和惊群事件的处理
- nginx源码分析--内存对齐处理
- nginx源码分析--多阶段请求处理
- Nginx源码分析 ——Nginx的进程模型
- Nginx源码分析 ——Nginx的进程通信方式
- Nginx源码分析 - 初探Nginx的架构
- Mybatis的注解应用之关系映射
- JAVA使用http发送post或get请求实例
- Swift 3.0 学习笔记-5-函数
- linux初学 unit2 练习
- 树莓派上安装turtlebot
- nginx源码分析—处理继承的sockets
- ASP.Net学习笔记008--ASP.Net揭秘之Input版自增补充说明
- 蓝桥杯2013年第四届决赛C_C++程序设计本科B组
- Module类
- Ubuntu1404+anconda2+python2.7 Tensorflow1.0安装
- 蓝桥杯:高精度算法
- Apache CXF前端应用(Frontend)
- 方法重载和方法覆盖的区别
- 每日一练之Palindrome Number【LeetCode No.9】—判断是否为回文数