前面的文章介绍了一个基于微线程的调度器框架,并测试了使用微线程实现远程调用的效率。
本文将微线程和网络事件框架结合起来,在微线程中处理所有的事件(网络消息,用户定时器事件),
这样,在事件回调函数中可以放心的发起远程调用而不用担心阻塞整个线程,只要还有未被阻塞的
微线程,就可以切换到那个微线程上去执行,继续等待在事件队列上处理新到的事件.
typedef struct coronet { netservice_t nets; msg_loop_t msgl; sche_t coro_sche; uint32_t last_check_timer; TimingWheel_t timer_ms;//精度50ms TimingWheel_t timer_s; //精度1s TimingWheel_t timer_m; //精度1分钟 }*coronet_t;
首先看下事件框架的定义,事件框架结构封装了一个微线程调度器,一个网络服务引擎,一个消息分发器,
还有3种不同精度的用户定时器.
使用者创建coronet后调用coronet_init_net绑定事件回调函数,之后调用coronet_init_coro创建微线程池,
然后调用coronet_run就可以进入事件循环.
下面看下微线程的主处理函数,这个函数要作为coronet_init_coro的第三个参数传入,跟线程的主函数有点类似,
微线程运行之后就会进入这个主函数,如下面的实现,这个主函数只是在一个循环中不断的提取消息并执行,如果
没有消息则会执行50ms的可被打断休眠(如果网络层有事件到达,休眠会被打断).
void* uthread_main_function(void *arg) { coronet_t coron = (coronet_t)arg; while(0 == isstop) { //等待事件的到来并处理,如果没有事件休眠50ms peek_msg(coron,50); } }
下面开看下peek_msg的实现:
void peek_msg(coronet_t coron,uint32_t ms) { assert(coron); assert(coron->nets); assert(coron->msgl); assert(coron->coro_sche); coro_t co = get_current_coro(); //首先检查是否有超时的coro,如果有唤醒,被唤醒后的coro会被投入到active_list_1 check_time_out(coron->coro_sche,GetCurrentMs()); //查看active_list_1中是否有coro等待执行,如果有,优先先执行coro _sche_next_1(coron->coro_sche,co); //检查用户定时器,如果有超时事件会触发一个消息并投递到消息队列中,后面的msg_loop_once会提取并执行 coronet_check_user_timer(coron); //等待消息的到来 msg_loop_once(coron->msgl,coron->nets,ms); }
这里先介绍下微线程调度器中的两个激活队列:active_list_1,active_list_2.激活队列分成两个优先级1为最高,2
为最低.其中2级队列存放所有普通的激活队列,例如微线程被创建之后,就会被投入到2级激活队列中。1级优先队列
存放的是优先级更高的微线程,例如rpc调用超时,sleep超时,还有收到rpc回应的微线程.调度器选择下一个被处理
的微线程时首先会从1级队列中提取,当1级队列为空时才调度2级队列中的微线程.
好了回到peek_msg,首先是检查是否有超时的微线程,然后执行_sche_next_1,_sche_next_1会尝试调度1级队列中的
微线程,如果1级队列中没有可以调度的对象,则调用msg_loop_once继续处理事件.
(在这里必须介绍下_sche_next_1的调度策略,它仅仅查看1级队列中是否有可调度对象,如果有则调度运行,没有立即返回,
这样做大大减少了不必要的微线程切换)
下面再来看下rpc的处理:
void process_rpc_return(rpacket_t r) { coro_t co = get_current_coro(); coro_t co_wakeup = (coro_t)rpacket_read_uint32(r); if(rpk_check(co_wakeup,r)) { co_wakeup->rpc_response = r; co_wakeup->_goback = co; //直接跳过去执行co_wakeup set_current_coro(co_wakeup); uthread_switch(co->ut,co_wakeup->ut,co); } }
process_rpc_return在网络包处理回调函数中被调用,当发现一个网络包代表了rpc回应时,就可以调用process_rpc_return
来处理这个rpc回应.这里的处理是设置一些成员变量,然后直接切换到需要被唤醒的微线程的上下文中继续执行.这里着重介绍
_goback成员,_goback成员被设置成从哪个微线程切换到目标微线程的。当目标微线程在执行的过程中,需要主动把执行权切换
出去的时候会首先切换到_goback所指向的微线程去.
项目地址如下:
https://github.com/sniperHW/kendylib/blob/master/netframework/coronet.h
Thinkpad笔记本电池的寿命延长与TPfancontrol共存的方法
Thinkpad笔记本电池的寿命延长与TPfancontrol共存的方法
2012年12月4日16:03:44
如题,笔者有一台Thinkpad E40 0579A22。众所周知锂化合物电池的充电次数是有限的,所以在不影响使用的前提下,应该尽量减少电池的充电次数。这个功能用联想官方自带的电源管理软件就能搞定。但是如果又想运行软件TPfancontrol来实现对散热风扇的控制,就有点麻烦了。因为在TPfancontrol与当前的电源管理驱动及软件有时候会产生冲突。导致黑屏,自动重启,自动休眠等等以外状况发生。为了避免这些以外发生,我的做法如下:
1、先把电池的充电阈值设置好。
自行定制充电阈值见下图,我是设置为电池电量低于10%的时候再进行充电,一直冲到100%(充满)为止。当然这不是优化电池寿命的阈值设置,我是因为最近经常要用到电池,所以才要充得满一点。一般优化电池存储是不要充满,具体值说法很多。反正大致保留一半左右的应该差不多了。
2、然后利用金山卫士将与电源管理有关的启动项以及计划任务都关掉。
用其它的方式关掉这些启动项也是一样的,如用优化大师,甚至直接调用windows的“系统配置”来进行修改都一样,方法:win+R,输入msconfig。
3、再用软件autorunschs.exe将电源管理驱动选设置为不启动(即在开机时不加载电源管理驱动)。
即将“驱动程序”选项下面的子项“IBMPMDRV”、"TPPWRIF"前面的勾去掉;“系统任务”选项下面与电源管理有关的子项的勾去掉(可能不去掉也可以,没做实验验证);“计划任务”选项下面与电源管理有关的子项的勾去掉;
“驱动程序”选项下面的子项“IBMPMDRV”、"TPPWRIF"前面的勾的两个图。
“系统任务”选项下面与电源管理有关的子项的勾去掉后如下图所示
“计划任务”选项下面与电源管理有关的子项的勾去掉后如下图所示
做完以上3步,重启后,电脑就不会加载电源管理驱动以及相应的电源管理软件了。但原先设置好的电池充电阈值依然生效。这个原因我猜是设置过后,电池的控制电路记住了这一设置。所以即便是不加载电源管理驱动和软件,它也会按照原来的设置执行。
最后有一点要注意下,即便是按上述步骤设置好后,电脑也按预先设想的那样工作。但如果什么时候把电池拆了下来,那么可能会导致电池充电阈值设置被清除,直接执行低于99%就充电的模式。所以没事就不要把电池给卸下来。
相关软件下载:
1、autorunschs.exe,直接点击以下链接下载
https://files.cnblogs.com/pingyidou/autorunschs.rar
2、TPfancontrol,直接点击以下链接下载0.62版
https://files.cnblogs.com/pingyidou/tpfc_v062.zip
更多版本请前往TPfancontrol官网查找,地址为http://www.staff.uni-marburg.de/~schmitzr/donate.html
如果对TPfancontrol软件本身的使用与设置有疑问,可以参考另一篇文章《让thinkpad更安静——控制风扇转速,解决tpfancontrol导致的关机、重启、黑屏》
文章链接为http://www.cnblogs.com/pingyidou/archive/2011/11/23/2260677.html