定时器问题--setitimer 求助

时间:2020-11-26 23:31:03
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <stdlib.h>
#include <signal.h>

bool bTimeOver = false;

void set_timer()
{
        struct itimerval itv, oldtv;
        itv.it_interval.tv_sec = 5;
        itv.it_interval.tv_usec = 0;
        itv.it_value.tv_sec = 0;
        itv.it_value.tv_usec = 0;

        setitimer(ITIMER_PROF,&itv,oldtv); 
}

void sigalrm_handler(int sig)
{
        bTimeOver = true;
        printf("timer signal.. %d\n", count);
}

void init_sigaction(void) 

       struct sigaction act; 
       act.sa_handler=sigalrm_handler; 
       act.sa_flags=0; 
       sigemptyset(&act.sa_mask); 
       sigaction(SIGPROF,&act,NULL); 


int main()
{
        init_sigaction;
        set_timer();
        while (!bTimeOver)
        {}
        exit(0);
}

这是通用的处理定时器的程序,请各位测试一些,时间到是bTimeOver = true,但为什么在main函数中调不出while循环?

在跟踪的时候发现定时器到时bTimeOver 会被置位true,但是就是跳不出while循环,请问是那个地方的问题,还是setitimer的用法没有对,请大家测试一下这个程序是否是我说的一样?

19 个解决方案

#1


你设置错了.

tv.it_interval.tv_sec = 5;                 //经过多成时间后重新设定settime()
itv.it_interval.tv_usec = 0;
itv.it_value.tv_sec = 0;                  //设定的时间,你设成0当然不行啦,改成其他值就可以了
itv.it_value.tv_usec = 0;

#2


to cceczjxy() 对不起,是我把程序粘贴错了,原来的代码为:
        struct itimerval itv, oldtv;
        itv.it_value.tv_sec = 5;
        itv.it_value.tv_usec = 0;
        itv.it_interval.tv_sec = 0;  //只运行一次
        itv.it_interval.tv_usec = 0;
        

        setitimer(ITIMER_PROF,&itv,oldtv);

我看了帮助文档,将it_interval设置为0的目的是此定时器只执行一次,按照这个代码还是跳不出while循环,你测试一下就知道了。

#3


init_sigaction;   //这的原因
 init_sigaction();  //这样就可以了.

#4


to cceczjxy() ,你说的是什么意思?能够说清楚一点吗?强烈期待中,谢谢!

#5


init_sigaction函数执行要求代括号。你不带大话,这个函数不执行。

#6


to cceczjxy() ,谢谢你看得这么仔细,不过这都是我粘贴代码的问题,我出现的问题应该与()是没有关系的,不然的话程序编译根本就通不过,希望在你的机子上测试一下,看是否是我说的问题,程序跳不出while这个循环。当然要保证上面的代码能够编译通过。

#7


期待高手测试一下程序再给我回复

#8


我没找到bool型在那个文件里,我给bTimeOver换成了 int型,测试通过了,运行也好使。能跳出来。
redhat linux 3.6.34,gcc
可以的。 

希望你你要找的高手尽快出现。

#9


init_sigaction;没括号,在我机器上能编译过去,但函数不执行。挺怪的,一前也没注意到。

#10


to cceczjxy() 谢谢你,谢谢你的热情,谢谢你的帮助,我按照你的环境用gcc编译后也能够正常的退出,但我原来用的是KDevelop建立的c++环境测试这段代码无论如何也不行?我用的是虚拟机,不知道你能否帮我测试一下,在KDevelop搭建这个环境,看能否通过,由于我的工程很大,所以用的是KDevelop,而我的测试程序是选了一段,感谢你呀,感谢你,我不晓得是否是KDevelop的问题还是虚拟机的问题。

#11


to cceczjxy() ,你能否提供一种更好的解决方法??

#12


乖乖, 居然敢用KDevelop ... ...
这种东西也能用? 还不如直接Makefile搞定

#13


while (!bTimeOver)  //要追查一下,bTimeover为什么不退出,可以换成bTimeover==false再试一下.
{
if(bTimeOver==true)
printf("true\n");
else printf("false\n");
printf("%d\n",!bTimerOver);
}

看看bTimerOver的值的情况.

#14


看上去是gcc优化导致的问题,估计你编译时有加入-O1/-O2之类的选项,你可以通过gcc -O2 -S 的方式看汇编代码,我在Red Hat Linux 9.0上看到的是对应的代码优化后会有问题。

修改方法有几种,直最接的一种是直接将bTimeOver加上修饰符volatile以避免gcc做不应该的优化。

#15


c语言本身没有bool型.
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/* C++ has a "bool" type built in. */
#ifndef __cplusplus
#ifndef HAVE_BOOL
#define HAVE_BOOL 1
typedef int bool;
#endif
#endif

你再看一下你的false和true的值.

#16


关注。。。

#17


to cceczjxy() ,对于你说的bool型变量,应该不会影响,因为可以将bTimeOver设置为int型的,测试还是同样的效果,而用gcc编译可以通过,我觉得这里可能还是KDevelop的问题吧。

to redex(cc),你觉得为什么不使用KDevelop,它编译环境很简单,而且对于大型的工程很适用。

to aria(*nix learner),我现在的问题是用gcc可以很好的运行,而在KDevelop环境下却不能正常工作,我想,这两个环境肯定是不同的,是不是与你说的优化有关系,你的意思是如果将bTimeOver加上修饰符volatile以避免gcc做不应该的优化,测试结果是否与KDevelop环境里面一样,也就是不会通过,是这样的吗?

#18


实际上我测试过用gcc/g++加入优化选项的话也是有同样的问题的,而不加优化选项就不会有问题,如源文件是a.c,
用gcc -Wall -O2 -o a a.c编译生成的程序a运行时会信号处理函数中会打印,但是bTimeOver永远不会为真,会一直死循环;而如果用gcc -Wall -o a a.c编译生成的程序a运行时信号处理函数中会打印,之后会正常退出。
因此解决方案是加入volatile修饰符就OK的。
你也可以在KDevelop编译出来的程序直接用objdump -d看反汇编的程序就知道原因的了。

#19


to aria(*nix learner) ( ) 谢谢你的指点,也就是说KDevelop可能加了优化选项。

#1


你设置错了.

tv.it_interval.tv_sec = 5;                 //经过多成时间后重新设定settime()
itv.it_interval.tv_usec = 0;
itv.it_value.tv_sec = 0;                  //设定的时间,你设成0当然不行啦,改成其他值就可以了
itv.it_value.tv_usec = 0;

#2


to cceczjxy() 对不起,是我把程序粘贴错了,原来的代码为:
        struct itimerval itv, oldtv;
        itv.it_value.tv_sec = 5;
        itv.it_value.tv_usec = 0;
        itv.it_interval.tv_sec = 0;  //只运行一次
        itv.it_interval.tv_usec = 0;
        

        setitimer(ITIMER_PROF,&itv,oldtv);

我看了帮助文档,将it_interval设置为0的目的是此定时器只执行一次,按照这个代码还是跳不出while循环,你测试一下就知道了。

#3


init_sigaction;   //这的原因
 init_sigaction();  //这样就可以了.

#4


to cceczjxy() ,你说的是什么意思?能够说清楚一点吗?强烈期待中,谢谢!

#5


init_sigaction函数执行要求代括号。你不带大话,这个函数不执行。

#6


to cceczjxy() ,谢谢你看得这么仔细,不过这都是我粘贴代码的问题,我出现的问题应该与()是没有关系的,不然的话程序编译根本就通不过,希望在你的机子上测试一下,看是否是我说的问题,程序跳不出while这个循环。当然要保证上面的代码能够编译通过。

#7


期待高手测试一下程序再给我回复

#8


我没找到bool型在那个文件里,我给bTimeOver换成了 int型,测试通过了,运行也好使。能跳出来。
redhat linux 3.6.34,gcc
可以的。 

希望你你要找的高手尽快出现。

#9


init_sigaction;没括号,在我机器上能编译过去,但函数不执行。挺怪的,一前也没注意到。

#10


to cceczjxy() 谢谢你,谢谢你的热情,谢谢你的帮助,我按照你的环境用gcc编译后也能够正常的退出,但我原来用的是KDevelop建立的c++环境测试这段代码无论如何也不行?我用的是虚拟机,不知道你能否帮我测试一下,在KDevelop搭建这个环境,看能否通过,由于我的工程很大,所以用的是KDevelop,而我的测试程序是选了一段,感谢你呀,感谢你,我不晓得是否是KDevelop的问题还是虚拟机的问题。

#11


to cceczjxy() ,你能否提供一种更好的解决方法??

#12


乖乖, 居然敢用KDevelop ... ...
这种东西也能用? 还不如直接Makefile搞定

#13


while (!bTimeOver)  //要追查一下,bTimeover为什么不退出,可以换成bTimeover==false再试一下.
{
if(bTimeOver==true)
printf("true\n");
else printf("false\n");
printf("%d\n",!bTimerOver);
}

看看bTimerOver的值的情况.

#14


看上去是gcc优化导致的问题,估计你编译时有加入-O1/-O2之类的选项,你可以通过gcc -O2 -S 的方式看汇编代码,我在Red Hat Linux 9.0上看到的是对应的代码优化后会有问题。

修改方法有几种,直最接的一种是直接将bTimeOver加上修饰符volatile以避免gcc做不应该的优化。

#15


c语言本身没有bool型.
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/* C++ has a "bool" type built in. */
#ifndef __cplusplus
#ifndef HAVE_BOOL
#define HAVE_BOOL 1
typedef int bool;
#endif
#endif

你再看一下你的false和true的值.

#16


关注。。。

#17


to cceczjxy() ,对于你说的bool型变量,应该不会影响,因为可以将bTimeOver设置为int型的,测试还是同样的效果,而用gcc编译可以通过,我觉得这里可能还是KDevelop的问题吧。

to redex(cc),你觉得为什么不使用KDevelop,它编译环境很简单,而且对于大型的工程很适用。

to aria(*nix learner),我现在的问题是用gcc可以很好的运行,而在KDevelop环境下却不能正常工作,我想,这两个环境肯定是不同的,是不是与你说的优化有关系,你的意思是如果将bTimeOver加上修饰符volatile以避免gcc做不应该的优化,测试结果是否与KDevelop环境里面一样,也就是不会通过,是这样的吗?

#18


实际上我测试过用gcc/g++加入优化选项的话也是有同样的问题的,而不加优化选项就不会有问题,如源文件是a.c,
用gcc -Wall -O2 -o a a.c编译生成的程序a运行时会信号处理函数中会打印,但是bTimeOver永远不会为真,会一直死循环;而如果用gcc -Wall -o a a.c编译生成的程序a运行时信号处理函数中会打印,之后会正常退出。
因此解决方案是加入volatile修饰符就OK的。
你也可以在KDevelop编译出来的程序直接用objdump -d看反汇编的程序就知道原因的了。

#19


to aria(*nix learner) ( ) 谢谢你的指点,也就是说KDevelop可能加了优化选项。

#20