您的位置 首页 解答

多线程中定时器的运用

不管是在进程还是线程,很多时候我们都会使用一些定时器之类的功能,这里就定时器在多线程的使用说一下。首先在linux编程中定时器函数有ala

不管是在进程仍是线程,许多时分咱们都会运用一些守时器之类的功用,这儿就守时器在多线程的运用说一下。首先在linux编程中守时器函数有alarm()和setitimer(),alarm()可以供给一个根据秒的守时功用,而setitimer可以供给一个根据奇妙的守时功用。 alarm()原型:
#i nclude
unsigned int alarm(unsigned int seconds);
这个函数在运用上很简略,第一次调用这个函数的时分是设置守时器的初值,下一次调用是从头设置这个值,并会回来上一次守时的剩余时刻。
setitimer()原型:
#i nclude
int setitimer(int which, const struct itimerval *value,
struct itimerval *ovalue);
这个函数运用起来略微有点说法,首先是第一个参数which的值,这个参数设置timer的计时战略,which有三种状况分别是:
ITIMER_REAL:运用体系时刻来计数,时刻为0时宣布SIGALRM信号,这种守时可以得到一个精准的守时,当然这个守时是相对的,由于到了微秒等级咱们的处理器自身就不行精确。
ITIMER_VIRTUAL:运用进程时刻也便是进程分配到的时刻片的时刻来计数,时刻为0是宣布SIGVTALRM信号,这种守时明显不行精确,由于体系给进程分配时刻片不由咱们操控。
ITIMER_PROF:上面两种状况都可以触发
第二个参数参数value涉及到两个结构体:
struct itimerval {
struct timeval it_interval;
struct timeval it_value;
};

struct timeval {
long tv_sec;
long tv_usec;
};
在结构体itimerval中it_value是守时器当时的值,it_interval是当it_value的为0后从头填充的值。而timeval结构体中的两个变量就简略了一个是秒一个是微秒。
上面是这两个守时函数的阐明,这个函数运用本不是很难,可以说是很简略,但是碰到详细的运用的时分或许就遇到问题了,在多进程编程中运用一般不会碰到什么问题,这儿说的这些问题首要体现在多线程编程中。比方下面这个程序
#i nclude #i nclude
#i nclude
#i nclude
#i nclude
#i nclude

void sig_handler(int signo)
{
alarm(2);
printf(“alarm signal”);
}

void *pthread_func()
{
alarm(2);
while(1)
{
pause();
}
}

int main(int argc, char **argv)
{
pthread_t tid;
int retval;

signal(SIGALRM, sig_handler);

if((retval = pthread_create(&tid, NULL, pthread_func, NULL)) < 0)
{
perror(“pthread_create”);
exit(-1);
}

while(1)
{
printf(“main thread”);
sleep(10);
}
return 0;
}
这个程序的抱负成果是:
main thread
alarm signal
alarm signal
alarm signal
alarm signal
alarm signal
main thread
可事实上并不是这样的,它的成果是:
main pthread
alarm signal
main pthread
alarm signal
main pthread
为什么会呈现这种状况呢?是由于发送给作业线程的信号中止的主线程的sleep,而且这个中状况只影响主线程而不会影响到其他的作业线程。咱们怎样才干处理这种问题呢,最简略的办法是修正这个程序,修正这个线程主线程运用alarm,作业线程运用sleep。这样就可以到达咱们的要求,但是有时分有不能简略的这样操作。所以咱们就需要进一步的修正咱们的程序。在这儿我第一个想到的是运用signal(SIGALRM, SIG_IGN),但是这个是设置整个进程对这个信号的呼应方法,通过测验也的确不能完结我希望的功用,那么怎样办呢?有这样一个函数pthread_sigmask,线程中的信号屏蔽,函数的原型及相关函数为:
#i nclude
int pthread_sigmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);
函数中第一个参数how有三个值SIG_BLOCK、SIG_SETMASK和SIG_UNBLOCK这儿咱们是用第二个值SIG_SETMASK
int sigemptyset(sigset_t *set);
int sigaddset(sigset_t *set, int signum);
然后咱们改造咱们的程序为:
#i nclude #i nclude
#i nclude
#i nclude
#i nclude
#i nclude

void sig_handler(int signo)
{
alarm(2);
printf(“alarm signal”);
}

void *pthread_func()
{
alarm(2);
while(1)
{
pause();
}
}

int main(int argc, char **argv)
{
pthread_t tid, tid_1;
int retval;

signal(SIGALRM, sig_handler);

if((retval = pthread_create(&tid, NULL, pthread_func, NULL)) < 0)
{
perror(“pthread_create”);
exit(-1);
}

sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGALRM);
pthread_sigmask(SIG_SETMASK,&sigset,NULL);

while(1)
{
printf(“main pthread”);
sleep(10);
}
return 0;
}
这个时分咱们就可以看到咱们想要的成果了。
这儿再附一个setitimer的运用典范
#i nclude #i nclude
#i nclude
#i nclude
#i nclude
#i nclude

struct itimerval timerval;
void sig_handler(int signo)
{
printf(“alarm signal”);
}


void *pthread_func()
{

setitimer(ITIMER_REAL, &timerval, NULL);
while(1)
{
pause();
}
}

int main(int argc, char **argv)
{
pthread_t tid;
int retval;
timerval.it_interval.tv_sec = 2;
timerval.it_interval.tv_usec = 0;
timerval.it_value.tv_sec = 2;
timerval.it_value.tv_usec = 0;

signal(SIGALRM, sig_handler);

if((retval = pthread_create(&tid, NULL, pthread_func, NULL)) < 0)
{
perror(“pthread_create”);
exit(-1);
}

sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGALRM);
pthread_sigmask(SIG_SETMASK,&sigset,NULL);

while(1)
{
printf(“main thread”);
sleep(5);
}


return 0;

}

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/changshang/jieda/260771.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部