- 论坛徽章:
- 0
|
1.2.1 全局变量
从第106行开始,都是POLLING相关的全局变量.首先是建立一SYSCTL树的节点.下图中的SYSCTL_NODE宏代表在父节点_kern下建立一个_kern_polling节点.
SYSCTL_NODE(_kern, OID_AUTO, polling, CTLFLAG_RW, 0, "Device polling parameters");
下图中的变量全部可用sysctl来查看,大部分都可以调整设置.这些全局变量都是使用宏SYSCTL_UINT把他们加入到_kern_polling节点下,成为该节点的叶子.之所以这样,是因为可以通过用户区来调整这些参数.
-----------------------------------------------------------------------------------------------------
static u_int32_t poll_burst = 5; ------ kern_poll.cstatic u_int32_t poll_each_burst = 5;
static u_int32_t poll_burst_max = 150;
static u_int32_t poll_in_idle_loop=0;
u_int32_t poll_in_trap;
static u_int32_t user_frac = 50;
static u_int32_t reg_frac = 20 ;static u_int32_t short_ticks;
static u_int32_t lost_polls;
static u_int32_t pending_polls;
static int residual_burst = 0;
static u_int32_t poll_handlers;
static int polling = 0;
static u_int32_t phase;
static u_int32_t suspect;
static u_int32_t stalled;
static u_int32_t idlepoll_sleeping; ------ kern_poll.c
----------------------------图1-2-2 ----------------------------
在图1-2-2中.这些变量按功能分可分为 3 大类.
A. 开关型:
polling: 初始为0,即默认为不打开轮询功能.要打开轮询功能,必须用:
#sysctl kern.polling=1
poll_in_idle_loop:该参数用于poll_idle函数,用来确定是否进入一低优先权的循环轮询中.即CPU空闲时是否来执行轮询.
poll_in_trap:此参数不但是在陷入时是否执行轮询的开关,而且其值也是在陷入(trap)时执行多少次轮询
B. 算法参数
poll_each_burst:一个基本的轮询次数,很多其他变量都来和他进行比较(主要是空闲时执行轮询或陷入时执行轮询).该值系统默认是5,
poll_burst:一个动态的轮询次数,主要用于根据核心(轮询)占用的时间片调整轮询次数,在核心(轮询)时间片小于预定的时间片时,该值加1,当核心(轮询)时间片过长,导致丢失一个或更多的时钟嘀嗒时,该值将减去该值的8分之1.这种算法是FreeBSD中轮询技术的主要算法.当然有一定的局限性.当网络分组快速增加时,此算法只是加1来增加次数再来调用软件中断,从而形成软中断暴增的做法并不好.而且在占用时间片过长时的减8分之1的做法也缺少理论依据.
poll_burst_max:轮训的最大值,该值是用来限制poll_burst在累加过程中的最大量.当然该值可以调整.他的调整范围在后面讲的两个宏之内.
user_frac:用户区占用的CPU时间片的百分比.该值用来确定核心(轮询)所占时间片是否有剩余,如果有的话就调整动态值poll_burst,使其加1.
residual_burst:在正常的轮询次数中,都是以poll_each_burst为标准的,而当动态的poll_burst>poll_each_burst时候,就会产生剩余没轮询的次数,该次数就是residual_burst,当然其结果就是继续轮询完residual_burst.
idlepoll_sleeping:该值的使用前提是poll_in_idle_loop变量开关已经打开,即在CPU空闲时支持轮询.系统置该值为0,可以直接进入到CPU空闲时的轮询代码中;如果poll_in_idle_loop变量开关还没开放,系统会给该值置1,也就是说.该值其实是一个CPU空闲时是否进入轮询代码的状态,
reg_frac:在整个循环代码执行了该值的次数之后,就进行检查网卡的状态寄存器.看看网卡是否有什么问题.
pending_polls:在进入轮询前(我们有个时钟嘀嗒钩子函数),此参数加1,再轮询后会对其减1,再次进入时钟嘀嗒后半部分会判断是否平衡,如果由于轮询时间过长,此次嘀嗒便会错过.
C. 调试与参考
short_ticks:每次时钟嘀嗒钩子函数所花的时间如果小于5毫秒.那这种间隔时间太短了.这是以HZ=100来计算的.源代码作者认为.在100M卡时,HZ数调整到1000比较合适,那么我们的时钟嘀嗒钩子函数所花时间在小于0.5毫秒是合适的.
lost_polls: 由于pending_polls的不平衡.记录一次嘀嗒时间错过,该值会不停的累加,给系统管理员提示可以调整poll_burst_max值小一些.或根据情况把user_frac(用户占用CPU时间片的百分比)的值调的更小些.
poll_handlers:有多少个网络设备支持并注册了轮询.
phase:指示轮询进行到了哪个阶段.轮询代码共分为6个阶段.
0阶段代表是初始阶段或上次轮询的结束.
1阶段时钟嘀嗒钩子函数在设置网络软中断(轮询中断)前
2阶段时钟嘀嗒钩子函数在设置网络软中断(轮询中断)后.
3阶段是进入软中断netisr_poll前.
4阶段是从软中断netisr_poll中出来.
5阶段是进入软中断netisr_pollmore前
6阶段是从软中断netisr_pollmore中出来.
suspect:由于最后的软中断netisr_pollmore在处理时会再完成时把阶段标志phase置为0(即一次POLLING的完成,),或出现其他未完成情况时进入阶段5和6.那么就是说.我们的时钟嘀嗒钩子在最初时小于2阶段的话,一定是在0阶段.如果出现1或2阶段的话就意味着时钟硬件中断发生了嵌套.此值在出现这种问题时进行记录.
stalled:由于pending_polls太大(大于100),也就是说由于每次轮询时间过长,以至于轮询丢失了太多嘀嗒,当到达100次时,该值加1.(源代码的作者认为不会发生此类事情,除了在网卡激活时)
以上是一些参数说明,你可以参照下.(不过是基于5.3的)
另外,请开空闲HOOK. |
|