一段代码,在单核/多核环境下运行,结果不一样,求高手解释!
我测试linux(centos5.6)上面的信号是否是安全的,不会丢失(哪怕cpu占用率100%的时候)。
发现一个奇怪的现象。下面一小段代码的主要功能是,创建两个计时器,定时输出一段字符串,其中第二个计时器做了一些消耗cpu的计算。我是在windows xp sp3的vbox 4.1下面安装的linux。
我发现单cpu机器运行和多cpu机器运行,结果是不一样的,这到底是为什么?
代码:
- C/C++ code
#include<signal.h> #include<stdio.h> #include<stdlib.h> #include<time.h> #include<unistd.h> int count1=0,count2=0; void handler1(int sig,siginfo_t*,void*){ if(sig==SIGRTMIN){printf("Timer 1s:%d\n",++count1);} } void handler2(int sig,siginfo_t*,void*){ if(sig==SIGRTMIN+1){printf(" Timer 2s:%d\n",++count2);} for(int i=0;i<2000000000;++i){ int j=i+2; int k=j*j; } } timer_t createTimer(int sig, double secs){ sigevent sev; timer_t timerid; sev.sigev_notify=SIGEV_SIGNAL; sev.sigev_signo =sig; sev.sigev_value.sival_ptr=&timerid; if(timer_create(CLOCK_REALTIME,&sev,&timerid)==-1)return 0; long freq_nanosecs=(long)secs*1000000000; itimerspec its; its.it_value.tv_sec =freq_nanosecs/1000000000; its.it_value.tv_nsec =freq_nanosecs%1000000000; its.it_interval.tv_sec =its.it_value.tv_sec; its.it_interval.tv_nsec=its.it_value.tv_nsec; if(timer_settime(timerid,0,&its,NULL)==-1)return 0; return timerid; } int main(void){ struct sigaction sa; sa.sa_flags=SA_SIGINFO; sa.sa_sigaction=handler1; sigemptyset(&sa.sa_mask); if(sigaction(SIGRTMIN,&sa,NULL)==-1)return 1; sa.sa_sigaction=handler2; if(sigaction(SIGRTMIN+1,&sa,NULL)==-1)return 2; createTimer(SIGRTMIN, 1); createTimer(SIGRTMIN+1,2); int left=10; do{left=sleep(left);}while(left>0); return 0; } 运行结果和发现:
(1)当第二个计时器没有消耗cpu的计算时(我注释掉for循环),程序的结果如我的预期:
Timer 1s:1
Timer 1s:2
Timer 2s:1
Timer 1s:3
Timer 1s:4
Timer 2s:2
Timer 1s:5
Timer 1s:6
Timer 2s:3
Timer 1s:7
Timer 1s:8
Timer 2s:4
Timer 1s:9
Timer 1s:10
Timer 2s:5
(2)当for循环存在的时候,如果此时的运行环境是1个cpu,那么结果仍然是正确的。不过,每次打印之间间隔的时间变得很长了,总运行时间也远不止10s。
(3)当for循环存在的时候,如果此时的运行环境是多个cpu(vbox可以更改cpu个数),那么结果就是非常奇怪的:
Timer 1s:1
Timer 1s:2
Timer 2s:1
Timer 2s:2
Timer 2s:3
Timer 2s:4
Timer 2s:5
Timer 2s:6
Timer 2s:7
Timer 2s:8
Timer 2s:9
(4)我的初步分析:
当机器只有一个cpu的时候,OS和进程轮流使用时间片。两个timer轮流使用cpu时间,当第二个timer在消耗cpu的时候,期间OS并没有给两个计时器增加时间,也不会通知两个计时器的事件。
但是多cpu的时候,OS占用一个cpu,不断的给两个计时器计时。所以第二个timer不断的被OS提醒运行,占用了进程的所有的cpu时间,而第一个timer的计时信号则不断的被OS插入提醒列表,但是没有被响应。
这也就是说明linux的行为,在cpu数量发生变化的时候,是会改变的?
[解决办法]
在aix环境下试验了一下,行为与lz的第3种情况类似
不仅第一个timer没有执行,连sleep也没有执行
看样子是全部的时间都给了timer2
可能与timer2中的for循环的执行耗时超过2s有关
信号处理程序的优先级相对较高,所以sleep得不到调度