根据Nginx(0.7.67版本)的代码,对Nginx基本的进程创建,进程主体以及事件处理进行了简要的分析。
基本上,父进程(即主进程)一开始会初始化及读取配置,并加载各模块的功能,然后fork()出N个子进程(即工作进程),具有相同的工作逻辑 和功能。父进程负责监听信号(如HUP,QUIT等),通过socket pair把信号传递给子进程(子进程间一般不通信)。子进程通过事件来处理父进程传递的信号。因为每个子进程都共享服务监听端口(如http 80),当用户发送请求时,会触发子进程的事件调用函数。因此在accept()请求的时候,需要用到mutex,保证只有一个工作进程接受并处理请求。
Nginx主进程的入口是跟一般的程序一样的main()函数,它的代码是这样的:
- int ngx_cdecl main(int argc, char *const *argv)
- {
- /*...*/
- //nginx 启动的时候会尝试从环境变量中读取前次执行时候的监听套接口的id,
- //并会创建对应数量的ngx_listening_t结构变量(存于 cycle->listening数组中),
- //然后调用这个接口通过getsockname,getsockopt等系统调用把原来套接口的属性信息和
- //设置参数读取出来去设置那些新创建的ngx_listening_t结构变量,这样就继承了前次执行
- //时候的监听套接口了,这个接口是在 ngx_init_cycle之前调用的
- if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
- return 1;
- }
- /*...*/
- //ngx_modules数组在objs/ngx_modules.c定义
- ngx_max_module = 0;
- for (i = 0; ngx_modules[i]; i++) {
- ngx_modules[i]->index = ngx_max_module++; //将每个模块编号
- }
- //ngx_init_cycle()函数,这是个比较重要的函数,被main, ngx_master_process_cycle
- //和ngx_single_process_cycle 调用, 其中后两者是在reconfigure的时候被调用的。
- //它主要工作是,初始化cycle是基于旧有的cycle进行的; 会继承old cycle的很多属性,
- //比如log等, 但是同时会对很多资源重新分配, 比如pool, shared mem, file handler,
- //bind/listen socket等,同时清除旧有的cycle的资源
- //读取配置文件也是在这里完成的
- cycle = ngx_init_cycle(&init_cycle);
- if (ngx_process == NGX_PROCESS_SINGLE) {
- ngx_single_process_cycle(cycle);
- }
- else {
- //一般采用多进程处理请求
- ngx_master_process_cycle(cycle);
- }
- }
- //ngx_start_worker_processes()函数,这个函数按指定数目n,以ngx_worker_process_cycle()函
- //数为参数调用ngx_spawn_process()创建work进程并初始化相关资源和属性;
- //执行子进程的执行函数ngx_worker_process_cycle;向之前已经创建的所有worker广播当前创建的
- //worker进程的信息;每个进程打开一个通道(ngx_pass_open_channel())
- //n是worker process的数目
- //type 即创建新进程式的方式,如NGX_PROCESS_RESPAWN, NGX_PROCESS_JUST_RESPAWN
- static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)
- {
- ngx_int_t i;
- ngx_channel_t ch;
- ch.command = NGX_CMD_OPEN_CHANNEL;
- for (i = 0; i < n; i++) {
- //从config读取CPU的分配
- cpu_affinity = ngx_get_cpu_affinity(i);
- //ngx_spawn_process中设置ngx_process_slot为被分配到子进程的
- //空闲slot
- ngx_spawn_process(cycle, ngx_worker_process_cycle, NULL,
- "worker process", type);
- ch.pid = ngx_processes[ngx_process_slot].pid;
- ch.slot = ngx_process_slot;
- ch.fd = ngx_processes[ngx_process_slot].channel[0];
- //ngx_pass_open_channel 把这个worker的channel[0]和进程id
- //在进程表中的偏移slot广播(ngx_write_channel())给所有其他已经
- //创建的worker。
- //这样,创建完所有进程之后,每个worker就获得了所有其他worker的
- //channel[0]了
- ngx_pass_open_channel(cycle, &ch);
- }
- }
- ngx_pid_t ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data, char *name, ngx_int_t respawn)
- {
- /*...*/
- //如果类型为NGX_PROCESS_DETACHED,则说明是热代码替换(热代码替换也是通过这
- //个函数进行处理的),因此不需要新建socketpair。
- if (respawn != NGX_PROCESS_DETACHED) {
- //建立socketpair
- //创建socketpair用于进程间通信,master进程为每个worker创建一对
- //socket, master进程空间打开所有socketpair的channel[0],
- //channel[1]两端句柄。
- //当创建一个worker的时候,这个worker会继承master当前已经创建并
- //打开的所有socketpair。
- //这个worker初始化的时候(调用ngx_worker_process_init)会关闭
- //本进程对应socketpair的channel[0]和其他worker对应的
- //channel[1],保持打开本进程对应socketpair的channel[1]和其他
- //worker对应的channel[0],并监听本进程对应socketpair的
- //channel[1]的可读事件。这样,每个worker就拥有了其他worker的
- //channel[0],可以sendmsg(channel[0], ...)向其他worker发送消息
- /*...*/
- }
- /*...*/
- //创建子进程
- pid = fork();
- switch (pid) {
- case -1:
- ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
- "fork() failed while spawning "%s"", name);
- ngx_close_channel(ngx_processes[s].channel, cycle->log);
- return NGX_INVALID_PID;
- //在子进程里,执行传递进来的子进程的函数
- case 0:
- ngx_pid = ngx_getpid();
- //调用ngx_worker_process_cycle()
- //注意:这个函数中定义了子进程处理事件的循环,即子进程不会
- //执行这个函数之后的语句
- proc(cycle, data);
- break;
- default:
- break;
- }
- }
- //worker进程的主体
- static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
- {
- //设置一些环境变量
- //调用所有模块的init_process钩子函数
- //将其他进程的channel[1]关闭,自己的除外
- //子进程继承了父进程的ngx_processes数组,但子进程只监听自己的channel[1]
- //将自己的channel[0]关闭
- //因为自己的channel[0]是给其他子进程,用来发送消息的sendmsg
- //调用ngx_add_channel_event()函数,给ngx_channel注册一个读事件处理函数。
- ngx_worker_process_init(cycle, 1);
- //主循环,处理事件
- for ( ;; ) {
- /*...*/
- //调用epoll,周期性监听事件
- //先接收连接(并不处理事件),以及处理进程间信号(如有)
- //处理accept queue和event queue里面的事件
- ngx_process_events_and_timers(cycle);
- /*...*/
- }
- /*...*/
- }
相关推荐
修炼成Javascript中级程序员必知必会_资源分享
内容概要:本文详细介绍了如何使用MATLAB的深度学习工具箱,在果树病虫害识别任务中从数据准备、模型设计、训练优化到最后的模型评估与应用全流程的具体实施步骤和技术要点。涵盖了MATLAB深度学习工具箱的基本概念及其提供的多种功能组件,如卷积神经网络(CNN)的应用实例。此外,文中还具体讲述了数据集的收集与预处理方法、不同类型的深度学习模型搭建、训练过程中的超参数设定及其优化手段,并提供了病虫害识别的实际案例。最后展望了深度学习技术在未来农业领域的潜在影响力和发展前景。 适合人群:对深度学习及农业应用感兴趣的科研人员、高校师生和相关从业者。 使用场景及目标:①希望掌握MATLAB环境下构建深度学习模型的方法和技术细节;②从事果树病虫害管理研究或实践,寻找高效的自动化解决方案。 阅读建议:在阅读本文之前,建议读者熟悉基本的MATLAB编程环境及初步了解机器学习的相关概念。针对文中涉及的理论和技术难点,可以通过官方文档或其他教程进行补充学习。同时,建议动手实践每一个关键点的内容,在实践中加深理解和掌握技能。
nodejs010-nodejs-block-stream-0.0.7-1.el6.centos.alt.noarch.rpm
机械模型与技术交底书的融合:创新点详解与解析,机械模型加技术交底书,有创新点 ,机械模型; 技术交底书; 创新点,创新机械模型与技术交底书详解
免费JAVA毕业设计 2024成品源码+论文+数据库+启动教程 启动教程:https://www.bilibili.com/video/BV1SzbFe7EGZ 项目讲解视频:https://www.bilibili.com/video/BV1Tb421n72S 二次开发教程:https://www.bilibili.com/video/BV18i421i7Dx
免费JAVA毕业设计 2024成品源码+论文+数据库+启动教程 启动教程:https://www.bilibili.com/video/BV1SzbFe7EGZ 项目讲解视频:https://www.bilibili.com/video/BV1Tb421n72S 二次开发教程:https://www.bilibili.com/video/BV18i421i7Dx
nodejs010-nodejs-cmd-shim-1.1.0-4.1.el6.centos.alt.noarch.rpm
西门子四轴卧加后处理系统:828D至840D兼容,四轴联动高效加工解决方案,支持图档处理及试看程序。,西门子四轴卧加后处理,支持828D~840D系统,支持四轴联动,可制制,看清楚联系,可提供图档处理试看程序 ,核心关键词:西门子四轴卧加后处理; 828D~840D系统支持; 四轴联动; 制程; 联系; 图档处理试看程序。,西门子四轴卧加后处理程序,支持多种系统与四轴联动
基于黏菌优化算法(SMA)的改进与复现——融合EO算法更新策略的ESMA项目报告,黏菌优化算法(SMA)复现(融合EO算法改进更新策略)——ESMA。 复现内容包括:改进算法实现、23个基准测试函数、多次实验运行并计算均值标准差等统计量、与SMA对比等。 程序基本上每一步都有注释,非常易懂,代码质量极高,便于新手学习和理解。 ,SMA复现;EO算法改进;算法实现;基准测试函数;实验运行;统计量;SMA对比;程序注释;代码质量;学习理解。,标题:ESMA算法复现:黏菌优化与EO算法融合改进的实证研究
基于MATLAB的Stewart平台并联机器人仿真技术研究与实现:Simscape环境下的虚拟模拟分析与应用,MATLAB并联机器人Stewart平台仿真simscape ,MATLAB; 并联机器人; Stewart平台; 仿真; Simscape; 关键技术。,MATLAB中Stewart平台并联机器人Simscape仿真
Grad-CAM可视化医学3D影像
探索comsol泰勒锥:电流体动力学的微观世界之旅,comsol泰勒锥、电流体动力学 ,comsol泰勒锥; 电流体动力学; 锥形结构; 电场影响,COMSOL泰勒锥与电流体动力学研究
免费JAVA毕业设计 2024成品源码+论文+数据库+启动教程 启动教程:https://www.bilibili.com/video/BV1SzbFe7EGZ 项目讲解视频:https://www.bilibili.com/video/BV1Tb421n72S 二次开发教程:https://www.bilibili.com/video/BV18i421i7Dx
PFC6.03D模型动态压缩模拟与SHPB霍普金森压杆系统理论及实验数据处理技术解析,PFC6.03D模型,动态压缩模拟,还包括: SHPB霍普金森压杆系统理论知识介绍,二波法和三波法处理实验数据,提出三波波形,计算动态压缩强度等 ,PFC模型; 动态压缩模拟; SHPB霍普金森压杆系统; 理论介绍; 二波法处理; 三波法处理; 三波波形; 动态压缩强度。,"PFC模型下的动态压缩模拟及SHPB理论实践研究"
ProASCI 开发板原理图,适用于A3P3000
免费JAVA毕业设计 2024成品源码+论文+录屏+启动教程 启动教程:https://www.bilibili.com/video/BV1SzbFe7EGZ 项目讲解视频:https://www.bilibili.com/video/BV1Tb421n72S 二次开发教程:https://www.bilibili.com/video/BV18i421i7Dx
1、文件内容:pykde4-devel-4.10.5-6.el7.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/pykde4-devel-4.10.5-6.el7.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、安装指导:私信博主,全程指导安装
基于Comsol模拟的三层顶板随机裂隙浆液扩散模型:考虑重力影响的瞬态扩散规律分析,Comsol模拟,考虑三层顶板包含随机裂隙的浆液扩散模型,考虑浆液重力的影响,模型采用的DFN插件建立随机裂隙,采用达西定律模块中的储水模型为控制方程,分析不同注浆压力条件下的浆液扩散规律,建立瞬态模型 ,Comsol模拟; 随机裂隙浆液扩散模型; 浆液重力影响; DFN插件; 达西定律模块储水模型; 注浆压力条件; 浆液扩散规律; 瞬态模型,Comsol浆液扩散模型:随机裂隙下考虑重力的瞬态扩散分析
A simple fast, easy use distributed file system written by golang(similar fastdfs).go-fastdfs
手机编程-1738391552157.jpg