linux的alarm
㈠ linux 的sleep()、usleep()、nanosleep()函数
原文地址: https://blog.csdn.net/weibo1230123/article/details/79139476
sleep()非系统调用,sleep()是在库函数中实现的,它是通过alarm()来设定报警时间,使用sigsuspend()将进程挂起在信号SIGALARM上。
sleep()只能精确到秒级上。sleep()会令目前的进程暂停,直到达到参数seconds 所指定的时间,或是被信号所中断。
return:若进程暂停到参数seconds 所指定的时间,成功则返回0,若有信号中断则返回剩余秒数。
除了时间单位为微秒以外,在使用上与sleep()差不多。还有就是实现也是不同的,sleep因为是用alarm实现的,所以时间单位为s ,而usleep的时间单位为us
,那肯定不是由alarm实现的,所以说它们的实现不同,但都是linux用的,而window下不能用,因为都是sleep和usleep都是在unistd.h下定义的。
return:若进程暂停到参数seconds 所指定的时间,成功则返回0,若有信号中断则返回剩余微秒数。
这个函数功能是暂停某个进程直到你规定的时间后恢复,参数req就是你要暂停的时间,其中req->tv_sec是以秒为单位,而tv_nsec以毫微秒为单位(10的-9次方秒)。由于调用nanosleep是是进程进入TASK_INTERRUPTIBLE,这种状态是会相应信号而进入TASK_RUNNING状态的,这就意味着有可能会没有等到你规定的时间就因为其它信号而唤醒,此时函数返回-1,切还剩余的时间会被记录在rem中。
return: 若进程暂停到参数 req所指定的时间,成功则返回0,若有信号中断则返回-1,并且将剩余微秒数记录在 rem中。
unistd.h 是 unix 系统标准头文件,用于系统调用,相当于win32中的windows.h,unistd.h 定义的函数只能用于UNIX环境中,而不能用于windows。所以sleep 和 usleep 只能用于linux下,而不能用于windows 。
nalosleep 和 其它时间日期操作函数一样都是定义在time.h中的,所以都适用
㈡ 关于linux中的pause()函数
这个函数是让程序暂停,直到等到有信号到来为止。
你这段程序实际就是一直等信号。
㈢ alarm的Linux C
alarm函数
要注意的是,一个进程只能有一个闹钟时间,如果在调用alarm之前已设置过闹钟时间,则任何以前的闹钟时间都被新值所代替。需要注意的是,经过指定的秒数后,信号由内核产生,由于进程调度的延迟,所以进程得到控制从而能够处理该信号还需要一些时间。
如果有以前为进程登记的尚未超时的闹钟时钟,而且本次调用的seconds值是0,则取消以前的闹钟时钟,其余留值仍作为alarm函数的返回值。
㈣ linux alarm 能在线程中用吗
不管是在进程还是线程,很多时候我们都会使用一些定时器之类的功能,这里就定时器在多线程的使用说一下。首先在linux编程中定时器函数有alarm()和setitimer(),alarm()可以提供一个基于秒的定时功能,而setitimer可以提供一个基于微妙的定时功能。
alarm()原型:
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
这个函数在使用上很简单,第一次调用这个函数的时候是设置定时器的初值,下一次调用是重新设置这个值,并会返回上一次定时的剩余时间。
setitimer()原型:
#include <sys/time.h>
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; /* next value */
struct timeval it_value; /* current value */
};
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
在结构体itimerval中it_value是定时器当前的值,it_interval是当it_value的为0后重新填充的值。而timeval结构体中的两个变量就简单了一个是秒一个是微秒。
上面是这两个定时函数的说明,这个函数使用本不是很难,可以说是很简单,但是碰到具体的应用的时候可能就遇到问题了,在多进程编程中使用一般不会碰到什么问题,这里说的这些问题主要体现在多线程编程中。比如下面这个程序:
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
void sig_handler(int signo)
{
alarm(2);
printf("alarm signal\n");
}
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\n");
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,线程中的信号屏蔽,函数的原型及相关函数为:
#include <signal.h>
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); /*清除信号集合set*/
int sigaddset(sigset_t *set, int signum); /*添加信号signum到信号集set中*/
然后我们改造我们的程序为:
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
void sig_handler(int signo)
{
alarm(2);
printf("alarm signal\n");
}
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\n");
sleep(10);
}
return 0;
}
这个时候我们就能够看到我们想要的结果了。
这里再附一个setitimer的使用范例:
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
struct itimerval timerval;
void sig_handler(int signo)
{
printf("alarm signal\n");
}
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\n");
sleep(5);
}
return 0;
}