`
liuzhaomin
  • 浏览: 207707 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Apache中预创建Preforking MPM 机制剖析(3)

阅读更多

6.3.3.5工作子进程管理

子进程通常被视为工作者,其组成了HTTP服务器的核心。它们负责处理对客户端的请求的处理。尽管多任务体系结构并不负责对请求的处理,不过他仍然负责创建子进程、对其进行初始化并且将客户端请求转交给它们进行处理。子进程的所有的行为都被封状在函数child_main()中。

6.3.3.5.1子进程的创建

在深入到子进程工作的内部细节之前,我们有必要了解一下主服务进程是如何创建子进程的。事实上,从主服务进程的最后的代码中也可以看出,主服务进程是通过调用make_child函数来创建一个子进程的,该函数定义如下:

static int make_child(server_rec *s, int slot)

该函数具有两个参数,slot是当前进程在记分板中的索引。

u的代码主要用于处理单进程。如前所述,单进程主要用于调试。对于单进程服务器而言,唯一的进程就是主服务进程,因此不需要创建任何额外的子进程,需要处理的就是转换主服务进程的角色为子服务进程,这种转变包括两部分:

...{

intpid;



if(slot+1>ap_max_daemons_limit)...{

ap_max_daemons_limit
=slot+1;

}




if(one_process)...{

apr_signal(SIGHUP,sig_term);

apr_signal(SIGINT,sig_term);

apr_signal(SIGQUIT,SIG_DFL);u

apr_signal(SIGTERM,sig_term);

child_main(slot);

return0;

}


上面

1)、处理信号。

6.3.3.5.2初始化、配置以及服务重启

(void)ap_update_child_status_from_indexes(slot,0,SERVER_STARTING,

(request_rec
*)NULL);



if((pid=fork())==-1)...{

ap_log_error(APLOG_MARK,APLOG_ERR,errno,s,
"fork:Unabletoforknewprocess");

(
void)ap_update_child_status_from_indexes(slot,0,SERVER_DEAD,

(request_rec
*)NULL);

sleep(
10);

return-1;

}


if(!pid)...{

RAISE_SIGSTOP(MAKE_CHILD);

AP_MONCONTROL(
1);

apr_signal(SIGHUP,just_die);

apr_signal(SIGTERM,just_die);

apr_signal(AP_SIG_GRACEFUL,stop_listening);

child_main(slot);

}




ap_scoreboard_image
->parent[slot].pid=pid;



return0;

}

主服务进程使用fork()创建子进程。每个子进程都具有独立的内存区域并且不允许读取其余子进程的内存。因此由主服务器一次处理配置文件要比由各个子进程各自处理明智的多。配置文件的相关信息可以保存在共享内存区域中,该内存区域可以被每一个子进程读取。由于不是每一个操作系统平台都支持共享内存的概念,因此主服务进程在创建子进程之前处理配置文件。子服务进程通常是父进程的克隆,因此它们与主服务进程具有相同的配置信息而且从来不会改变。

任何时候,如果管理员想更改服务器配置。他都必须让主服务进程重新读取配置信息。当前存在的子进程所拥有的则是旧的配置信息,因此它们都必须被替换为新产生的子进程。为了避免打断正在处理的HTTP请求,Apache提供了一种平稳启动的方法,该模式下允许子进程使用旧的配置信息进行处理直到其退出。

子进程的初始化可以在相应的MPM中找到,对于预创建Preforking MPM而言就是child_main()。该函数包括下面的几个步骤:

调用ap_init_child_modules()重新初始化模块:每一个模块都由主进程预先进行初始化。如果模块中分配系统资源或者决定于进程号,那么模块重新进行初始化就是必须的。

建立超时处理句柄:为了避免子进程的无线阻塞,Apache对客户端请求使用超时处理。其中使用警告,警告的概念与信号的概念非常类似,通常将报警时钟设置为给定的时间,而当报警响起的时候系统将离开请求的处理。

循环内还有两种初始化:

清除超时设置:重置报警定时器

清除透明内存池:在请求响应循环中每个内存的分配都涉及到透明内存池。在循环的开始,内存池必须进行清理。

将公告板中的status设置为ready

ptrans的创建,以及访问公告板,同时由于多个进程之间可能存在竞争,因此另外一个准备工作就是创建进程间的接受互斥锁。由于通常情况下,父进程都是使用fork生成子进程,此时子进程基本是父进程的克隆。一般情况下,Apache的启动都是使用超级用户进行的,因此子进程实际上也就具有与父进程等同的操作权限,父进程能够访问的资源子进程都能够访问。

staticvoidchild_main(intchild_num_arg)

...{

apr_pool_t
*ptrans;

apr_allocator_t
*allocator;

conn_rec
*current_conn;

apr_status_tstatus
=APR_EINIT;

inti;

ap_listen_rec
*lr;

intcurr_pollfd,last_pollfd=0;

apr_pollfd_t
*pollset;

intoffset;

void*csd;

ap_sb_handle_t
*sbh;

apr_status_trv;

apr_bucket_alloc_t
*bucket_alloc;



mpm_state
=AP_MPMQ_STARTING;



my_child_num
=child_num_arg;

ap_my_pid
=getpid();

csd
=NULL;

requests_this_child
=0;



ap_fatal_signal_child_setup(ap_server_conf);



apr_allocator_create(
&allocator);

apr_allocator_max_free_set(allocator,ap_max_mem_free);

apr_pool_create_ex(
&pchild,pconf,NULL,allocator);

apr_allocator_owner_set(allocator,pchild);

apr_pool_create(
&ptrans,pchild);

apr_pool_tag(ptrans,
"transaction");



ap_reopen_scoreboard(pchild,NULL,
0);

rv
=apr_proc_mutex_child_init(&accept_mutex,ap_lock_fname,pchild);

if(rv!=APR_SUCCESS)...{

ap_log_error(APLOG_MARK,APLOG_EMERG,rv,ap_server_conf,

"Couldn'tinitializecross-processlockinchild");

clean_child_exit(APEXIT_CHILDFATAL);

}


每个子进程在真正处理请求之前,都必须进行相关的资源准备工作,包括信号设置,私有内存池

Apache通常会将子进程的用户设置为一个普通的用户,比如nobody或者WWWRun之类从而来降低子进程的执行权限,原则上,子进程用户的权力应该尽可能的小。Unixd_setup_child将用户的ID从正在运行父进程的用户改变为在配置文件中规定的用户,如果不能改变用户的ID,子进程就立即退出。另外相关的初始化工作必须在unixd_setup_child()调用之前进行,因为一旦子进程权限降低,一些只能超级用户进行的初始化可能无法正常进行。

if(unixd_setup_child())...{

clean_child_exit(APEXIT_CHILDFATAL);

}


但是子进程具有与父进程相同的权限具有一定的潜在的危险。由于网络连接通常由子进程直接处理,因此如果黑客通过某种权限控制了子进程,那么他就能够任意的控制系统的。因此通常在进行了资源准备工作之后,

Ap_run_child_init调用child_init挂钩进行子进程本身的初始化。
ap_run_child_init(pchild,ap_server_conf);

ap_create_sb_handle(
&sbh,pchild,my_child_num,0);

(
void)ap_update_child_status(sbh,SERVER_READY,(request_rec*)NULL);

当所有的准备工作结束以后,子进程可以与客户进行会话。

80,但是在Apache中,则允许服务器在多个端口上同时进行侦听,这些侦听端口用结构ap_listen_rec进行描述:

listensocks=apr_pcalloc(pchild,

sizeof(*listensocks)*(num_listensocks));

for(lr=ap_listeners,i=0;i<num_listensocks;lr=lr->next,i++)...{

listensocks[i].accept_func
=lr->accept_func;

listensocks[i].sd
=lr->sd;

}




pollset
=apr_palloc(pchild,sizeof(*pollset)*num_listensocks);

pollset[
0].p=pchild;

for(i=0;i<num_listensocks;i++)...{

pollset[i].desc.s
=listensocks[i].sd;

pollset[i].desc_type
=APR_POLL_SOCKET;

pollset[i].reqevents
=APR_POLLIN;

}


mpm_state
=AP_MPMQ_RUNNING;

bucket_alloc
=apr_bucket_alloc_create(pchild);

一般的情况下,服务器只会侦听固定的端口,比如

描述了绑定到该端口的套接字,而bind_addr则描述了套接字必需关联的地址。Accept_func是一个回调函数,当从该侦听端口上接受到客户端连接的时候,该函数将被执行从而来处理连接。Active用以描述当前端口是否处于活动状态。

structap_listen_rec...{

ap_listen_rec
*next;

apr_socket_t
*sd;

apr_sockaddr_t
*bind_addr;

accept_functionaccept_func;

intactive;

}
;

sd

对于服务器端的多个侦听端口,Apache使用链表进行保存,因此next用以指向下一个侦听套接字结构。整个链表的用ap_listen_rec全局变量记录,因此沿着ap_listen_rec可以遍历所有的侦听套接字。与此同时,侦听端口的数目也保存在全局变量num_listensocks中。

上面的代码所作的事情无非就是生成指定的需要逐一遍历的文件结果集合。

任何时候,子进程如果要正常退出,其都必须由主进程通过终止管道通知,另一方面,子进程也将不停的检查终止管道。一旦发现需要退出,子进程将die_now设置为1,这时候实际上就自动退出循环。相反,如果子进程不需要退出,那么它所作的事情只有一个,就是使用poll对所有的端口进行轮询,直到某个端口准备完毕,则调用相关的连结处理函数进行处理。

while(!die_now)...{

current_conn
=NULL;

apr_pool_clear(ptrans);

if((ap_max_requests_per_child>0

&&requests_this_child++>=ap_max_requests_per_child))...{

clean_child_exit(
0);

}


(
void)ap_update_child_status(sbh,SERVER_READY,(request_rec*)NULL);

SAFE_ACCEPT(accept_mutex_on());

虽然多个子进程同属于一个父进程,但是多个子进程之间则是相互并行的,当多个子进程同时扫描侦听端口的时候,很可能发生多个子进程同时竞争一个侦听端口的情况。因此所有的子进程有必要互斥的等待TCP请求。

接受互斥锁能够确保只有一个子进程独占的等待TCP请求(使用系统调用accept())——这些都是侦听者所做的事情。接受互斥锁是控制访问TCP/IP服务的一种手段。它的使用能够确保在任何时候只有一个进程在等待TCP/IP的连接请求。

不同的操作系统有不同的接受互斥锁(Accept Mutex)的实现。有一些操作系统对于每一个子进程需要一个特殊的初始化阶段。它的工作方式如下:

调用过程accept_mutex_on():申请互斥锁或者等待直到该互斥锁可用

调用过程accept_mutex_off():释放互斥锁

prefork MPM中通过SAFE_ACCEPT(accept_mutex_on())实现子进程对互斥锁的锁定;而SAFE_ACCEPT(accept_mutex_off())则是完成互斥锁的释放。

if (num_listensocks == 1) {

offset = 0;

}

对于整个侦听套接字数组而言,任何时候只有一个侦听端口能被处理。Offset实际上描述了当前正在被处理的侦听端口在数组中的索引。如果当前服务器的侦听端口只有一个,那么几乎没有任何事情要做,也就没有所谓的轮询。

如果服务器配置使用多个侦听端口,那么Apache就必须使用poll()来确定客户正在连接哪个端口,然后我们就可以知道哪个端口正在受到访问,这样才能在这个端口上调用接受函数。如果轮询返回的值是EBADFEINTR或者EINVAL之类的错误,那么轮询并不应该被终止,但是如果返回的不是这些错误,那么子进程应该调用clean_child_exit退出。

else...{

for(;;)...{

apr_status_tret;

apr_int32_tn;

ret
=color: #00000
分享到:
评论

相关推荐

    Starman, Starman是高性能的preforking Perl PSGI web服务器.zip

    Starman, Starman是高性能的preforking Perl PSGI web服务器 电子邮件名称Starman - 高性能 preforking psgi/Plack网络服务器概要# Run app.psgi with the default settings&gt; starman# run w

    此工具是一个php定时任务管理工具,支持大量PHP定时脚本,采用预派生进程模型,父进程负责计算定时任务间隔逻辑向消息队列.zip

    3. 预派生进程模型是该工具的核心机制之一,该模型通过预创建子进程来提高任务处理效率。 4. 父进程负责计算定时任务间隔逻辑,并通过消息队列向子进程派发任务。 5. 消息队列的引入是为了异步传递任务指令,并保证...

    Monoceros, psgi/Plack服务器,带有事件驱动的连接管理器,preforking员工.zip

    Monoceros, psgi/Plack服务器,带有事件驱动的连接管理器,preforking员工 电子邮件名称Monoceros - psgi/Plack服务器,带有事件驱动的连接管理器,preforking工作者概要% plackup -s Monoceros --max-keepalive-...

    PSGI的HTTP服务器Starman.zip

    Starman 是一个高性能、preforking 和 PSGI 兼容的 HTTP 服务器,支持 HTTP/1.1、多网络接口支持以及 Unix Domain 套接字支持,可无缝进行重启,支持通过操作系统信号进行动态的worker池配置。 标签:...

    环境流体力学:河流流动模拟.zip

    光电材料仿真,电子仿真等;从入门到精通教程;含代码案例解析。

    C#实现Stewart六自由度平台反解算法及其应用

    内容概要:本文详细介绍了如何使用C#实现Stewart六自由度平台的逆解算法。首先定义了平台的基本结构,包括上下平台的半径、安装角度以及舵机零位偏移等参数。接着,通过欧拉角转换为旋转矩阵的方式实现了姿态转换,并在此基础上计算各个支腿的长度。文中还特别强调了一些常见的陷阱,如角度单位一致性、安装方向匹配、零位校准和数值稳定性等问题。此外,提供了具体的测试用例用于验证算法的正确性和性能。 适合人群:具有一定C#编程基础并对机械臂控制、飞行模拟器或手术机器人等领域感兴趣的开发者和技术人员。 使用场景及目标:适用于需要精确控制六自由度平台的应用场合,如飞行模拟器、手术机器人等。主要目的是通过数学模型将平台的姿态转换为具体的操作指令,从而实现精准定位与操控。 其他说明:文中不仅给出了完整的代码实现,还分享了许多实践经验,帮助读者更好地理解和应用该算法。同时提醒开发者在实际项目中需要注意的一些关键点,如行程限制检查、运动学奇异性检测等。

    夸克网盘批量处理助手,同步更新保存分享链接文件,增量更新文件,批量重命名文件夹,文件名称关键词替换

    夸克网盘批量处理助手,同步更新保存分享链接文件,增量更新文件,批量重命名文件夹,文件名称关键词替换

    XML.md

    XML.md

    MATLAB实现光纤光栅均匀与非均匀应变仿真及其在光学传感的应用

    内容概要:本文详细介绍了利用MATLAB进行光纤光栅的均匀应变和非均匀应变仿真的方法。文中提供了具体的代码实例,解释了如何通过调整光栅的基本参数如中心波长、光栅长度、有效折射率等,以及引入应变系数和应变分布函数,分别计算均匀应变和非均匀应变下光纤光栅的反射率,并展示了相应的反射率曲线图。此外,还讨论了这两种应变模式对光栅反射谱的不同影响,强调了非均匀应变可能导致的光谱畸变现象。 适用人群:对光纤光栅仿真感兴趣的研究人员和技术爱好者,尤其是那些希望通过MATLAB进行光器件设计和测试的人群。 使用场景及目标:①用于科研项目中光纤光栅特性的研究;②辅助工程师在实际工程项目中评估光纤光栅传感器的表现;③帮助学生理解光纤光栅的工作机制和应变对其性能的影响。 其他说明:文章不仅提供了详细的代码实现步骤,还分享了一些调试技巧和注意事项,有助于读者更好地理解和应用所介绍的技术。

    计算机网络基于b站的学习笔记

    计算机网络概念,计算机网络,互联网,互连网的区别;计算机网络的组成、功能;三种交换技术;计算机网络的性能指标;以及计算机网络的分类

    基于Simulink的ABS仿真模型及其PID控制策略的应用与优化

    内容概要:本文详细介绍了如何使用Simulink搭建防抱死制动系统(ABS)的仿真模型,并应用PID控制策略进行仿真分析。首先,文章解释了ABS系统的重要性和工作原理,然后逐步讲解了如何在Simulink中构建车轮动力学模块、制动压力模块等关键组件。接下来,文章深入探讨了PID控制策略的具体实现方法,包括PID参数的选择和调整技巧。通过多次仿真实验,展示了不同PID参数对ABS系统性能的影响,并提出了优化方案,如变增益策略和积分分离策略。最后,文章分享了一些实用的经验和技巧,如处理低速时的数值稳定性、应对路面突变等情况。 适合人群:对汽车工程、控制系统设计感兴趣的工程师和技术爱好者,尤其是那些希望深入了解ABS系统和PID控制策略的人群。 使用场景及目标:适用于希望在虚拟环境中研究和优化ABS系统性能的研究人员和工程师。主要目标是提高ABS系统的制动性能和安全性,确保在各种工况下都能保持最佳的制动效果。 其他说明:文中不仅提供了理论知识,还包括了大量的实际案例和代码片段,帮助读者更好地理解和应用所学内容。此外,作者还分享了许多实践经验,如如何处理仿真中的常见问题和优化策略。

    独子棋demo.rar

    独子棋demo.rar

    基于Maxwell-Simplorer的永磁同步电机SVPWM控制联合仿真研究

    内容概要:本文详细介绍了如何利用Maxwell和Simplorer进行矢量联合仿真,结合SVPWM(空间矢量脉宽调制)算法实现对永磁同步电机的精确控制。文章首先解释了SVPWM的基本原理及其Python实现,接着阐述了在Maxwell中建立电机模型并设置参数的具体步骤,以及在Simplorer中搭建控制系统的方法。文中还讨论了仿真过程中如何调整控制器参数以优化系统性能,并展示了如何通过分析仿真结果来评估控制效果。此外,文章探讨了将该方法应用于其他类型电机的可能性,如感应电机和开关磁阻电机。 适合人群:从事电机控制领域的研究人员和技术人员,尤其是对永磁同步电机和SVPWM算法感兴趣的读者。 使用场景及目标:适用于需要深入了解永磁同步电机控制原理的研究人员,帮助他们掌握Maxwell和Simplorer联合仿真的具体操作流程,提高对电机控制系统的理解和优化能力。 其他说明:文章不仅提供了详细的理论讲解,还附有大量代码片段和实践经验,有助于读者更好地理解和应用相关技术。同时,文章强调了实践中可能遇到的问题及解决方法,使读者能够在实际工作中避免常见错误。

    【太阳能电池片图像处理】基于边缘检测与频域滤波的预处理系统设计:图像倾斜校正及栅格去除(论文复现或解答,含详细代码及解释)

    内容概要:本文详细介绍了太阳能电池片在线颜色分选系统的图像预处理方法。针对采集的原始图像中存在的传送带背景和随机倾斜等问题,提出了完整的预处理流程。主要包括:倾斜校正(通过边缘检测和霍夫变换)、去除栅格干扰(频域滤波和形态学操作),以及对多种边缘检测算子(如Roberts、Sobel、Prewitt、Canny和LOG)的比较与分析。此外,还探讨了不同直线检测方法(如Radon变换、Hough变换及其改进版本)的应用,并优化了整个预处理流程,确保后续的颜色特征提取和分类准确性。 适用人群:从事计算机视觉、图像处理领域的研究人员和技术人员,特别是专注于工业自动化检测设备开发的工程师。 使用场景及目标:①实现太阳能电池片图像的倾斜校正,确保图像水平放置;②有效去除电池片表面栅线对颜色分析的影响;③为后续的颜色特征提取和分类提供高质量的输入数据;④比较不同边缘检测算子的效果,选择最适合特定任务的算子;⑤评估各种直线检测方法的性能,选择最优方案应用于实际生产环境中。 其他说明:文中不仅提供了详细的理论解释,还给出了具体的Python代码实现,帮助读者更好地理解和实践相关技术。同时,针对实际应用中的常见问题,如参数调优、光照一致性和异常处理等方面也给出了相应的建议。最后,通过一系列实验验证了所提方法的有效性,并提出了一些性能优化的方向。

    Comsol锂离子电池仿真:电化学-热耦合模型与多物理场分析助力电池热管理

    内容概要:本文详细介绍了利用Comsol进行锂离子电池仿真的技术和应用,特别是在电化学-热耦合模型和多物理场分析方面。文章首先阐述了电化学-热耦合模型在充放电循环中的应用,通过MATLAB伪代码展示了如何定义电池几何形状、材料属性、边界条件以及耦合电化学和热传递过程。接下来讨论了液冷仿真与电池热管理模型,通过Python伪代码解释了液冷通道的构建、流体属性的设置及其流动与热传递的求解。此外,文章还比较了锂电池产热模型下风冷和液冷的不同效果,并强调了产热计算的重要性。最后,文章分享了一些实用的经验和技术细节,如处理高倍率充电时的浓度极化、选择合适的湍流模型、刀片电池的建模技巧等。 适合人群:从事锂离子电池研究和开发的科研人员、工程师及相关领域的学生。 使用场景及目标:①理解和优化锂离子电池的热管理机制;②评估不同冷却方式(如风冷、液冷)的效果;③提高电池系统的性能和安全性。 其他说明:文中不仅提供了详细的理论背景和技术实现步骤,还分享了许多实践经验,有助于读者更好地掌握Comsol在锂离子电池仿真中的应用。

    智能驾驶领域AEB系统的安全距离与TTC切换优化算法及其应用场景

    内容概要:本文探讨了自动紧急制动系统(AEB)中安全距离与时间头时距(TTC)的优化方法。首先介绍了AEB系统的基本原理,包括安全距离和TTC的定义及计算方式。接着提出了基于机器学习的动态调整机制,通过分析历史驾驶数据,训练回归模型预测最优安全距离,并设计了基于规则的智能切换机制,根据车速选择合适的评估标准。此外,通过仿真测试验证了改进算法的有效性,展示了其在低速跟车、高速变道等场景中的优越表现。最后,讨论了联合仿真中的挑战,如多物理场耦合与时序同步问题,并提供了相应的解决方案。 适合人群:从事智能驾驶技术研发的专业人士,尤其是对AEB系统有研究兴趣的工程师和技术爱好者。 使用场景及目标:适用于希望深入了解AEB系统工作原理及优化方法的研发团队。目标是通过改进现有算法,提高AEB系统在各种驾驶场景下的鲁棒性和安全性。 其他说明:文中提到的技术细节和代码片段有助于读者更好地理解和实现相关算法。同时指出了现有研究存在的局限性,为进一步探索提供了方向。

    数据结构.md

    数据结构.md

    格式化输出.md

    格式化输出.md

    三相不平衡电网下模块化多电平变流器(MMC)的先进控制策略及其实现

    内容概要:本文详细探讨了在三相不平衡电网条件下,模块化多电平变流器(MMC)的多种控制策略及其具体实现方法。主要内容包括:利用双二阶广义积分器(DSOGI)进行正负序分离控制,通过PI控制器实现零负环流抑制,以及采用谐振控制器抑制二倍频功率波动。此外,文中还介绍了不同控制模式之间的动态切换逻辑,确保系统在各种工况下的稳定性和高效性。文章提供了详细的MATLAB、Python和Verilog代码片段,展示了各个控制环节的具体实现。 适合人群:从事电力电子、电力系统自动化领域的研究人员和技术人员,尤其是对MMC控制策略感兴趣的工程师。 使用场景及目标:适用于需要解决三相不平衡电网问题的研究项目和工业应用场景。主要目标是在电压跌落等恶劣工况下,确保MMC系统的稳定性和平滑运行,提高系统的鲁棒性和效率。 其他说明:文中引用了多篇相关领域的权威文献,为读者提供了进一步深入研究的方向。同时,作者强调了理论仿真与实际调试之间的差距,提醒读者在实验过程中需要注意的安全事项。

    Python编程与PyQt GUI应用开发

    本书是关于Python编程语言和使用PyQt框架开发图形用户界面(GUI)应用的全面指南。首先介绍了Python的基础知识,包括安装、与Python交互、编写第一个程序、数据类型、基本元素、注释、续行和打印等。随后,深入探讨了Python的算术运算、位运算、复数、决策、逻辑运算符、循环等核心概念。接着,书中详细讲解了序列(包括字符串、列表、元组和集合)、函数和模块、类(包括类声明、方法、继承、垃圾回收、运算符重载和描述符)、文件处理以及异常处理。最后,作者重点介绍了PyQt框架,包括安装、窗口和对话框的创建、使用代码和Qt Designer创建GUI应用程序、基础控件、事件处理、高级控件(如LCD时钟、日历、组合框、表格、Web页面和图形显示)、菜单和工具栏的使用。本书适合希望学习Python编程和GUI开发的读者。

Global site tag (gtag.js) - Google Analytics