一、alarm(unsigned int seconds)
函数原型
#include
unsigned int alarm(unsigned int seconds);
描述:
1.alarm函数可以设置一个计时器,当过了seconds秒的时间后,会产生信号SIGALRM
2.一个进程只能有一个闹钟时间。如果在调用alarm时,以前已经为该进程设置过闹钟时钟,而且它还没有超时,则将该闹钟时间的剩余值作为本次alarm函数的返回值。以前登记的闹钟时间被新值代替。
3.如果有以前登记过闹钟时间尚未超时,而且本次调用的seconds值为0,则取消该闹钟时间,剩余时间以返回值返回。
4.虽然SIGALRM的默认动作是终止进程,但是大多数使用闹钟的进程会在调用alarm函数之前设置该信号的处理程序以捕捉该信号。
二、pause()
函数原型
#include
int pause(void);
描述:
pause()使得调用进程或线程处于睡眠状态直到捕捉到一个信号。
只有执行了一个信号处理程序并从其返回时,pause才返回,此时pause()返回-1,errno设置为EINTR。
三、sleep
函数原型
#include
unsigned int sleep(unsigned int seconds);
描述:
sleep()使得调用程序挂起,直到过了seconds秒的时间,或者调用进程捕捉到一个信号并且从信号处理函数中返回。
返回值:
0:如果过了指定的时间后退出
!0:如果被信号中断退出,返回剩余的时间值。
四、用alarm和pause实现sleep
-
#include <signal.h>
-
#include <unistd.h>
-
-
typedef void (*signal_handler)(int);
-
-
signal_handler old_sig_handle;
-
-
static void sig_alrm(int signo)
-
{
-
-
}
-
-
unsigned int sleep1(unsigned int nsecs)
-
{
-
if((old_sig_handle = signal(SIGALRM,sig_alrm)) == SIG_ERR)
-
return nsecs;
-
alarm(nsecs);
-
pause();
-
signal(SIGALRM,old_sig_handle);
-
return (alarm(0));
-
}
-
-
int main(void)
-
{
-
printf("before sleep1......\n");
-
sleep1(5);
-
printf("after sleep1.......\n");
-
return 0;
-
}
-
#include <setjmp.h>
-
#include <unistd.h>
-
#include <signal.h>
-
-
static jmp_buf env_alrm;
-
-
-
static void sig_alrm(int signo)
-
{
-
longjmp(env_alrm,1);
-
}
-
-
unsigned int sleep2(unsigned int nsecs)
-
{
-
if(signal(SIGALRM,sig_alrm) == SIG_ERR)
-
return nsecs;
-
-
if(setjmp(env_alrm) == 0) {
-
alarm(5);
-
pause();
-
}
-
-
return(alarm(0));
-
}
-
-
static void sig_int(int signo)
-
{
-
int i,j;
-
volatile int k;
-
-
printf("\nsig_int starting\n");
-
for(i = 0 ;i < 300000; i++) //这段代码的作用主要是产生大于5s的计算,使得此信号处理函数处理时间大于sleep时间
-
for(j = 0; i < 4000; j++)
-
k += i*j;
-
printf("sig_int finished\n");
-
}
-
-
int main()
-
{
-
unsigned int unslept;
-
-
if(signal(SIGINT,sig_int) == SIG_ERR)
-
perror("signal(SIGINI) error");
-
unslept = sleep2(5);
-
printf("sleep2 returned: %u\n",unslept);
-
exit(0);
-
}
运行./a,过了5s后,
gwwu@hz-dev2.com:~/test>./a
sleep2 returned: 0
运行./a, 并且Ctrl+C终止
gwwu@hz-dev2.com:~/test>./a
^C
sig_int starting
sleep2 returned: 0
可见,程序中SIGINT的处理函数提前退出了。
五、posix实现sleep函数代码
#include
#include
#include
static void sig_alrm(int signo)
{
printf("in sig_alrm\n");
}
unsigned int sleep(unsigned int usecs)
{
sigset_t new_mask,old_mask,waitmask;
struct sigaction act,old_act;
unsigned int uslept;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
act.sa_handler = sig_alrm;
if(sigaction(SIGALRM,&act,&old_act) < 0)
printf("sigaction(SIGARLM) error\n");
sigemptyset(&new_mask);
sigaddset(&new_mask,SIGALRM);
if(sigprocmask(SIG_BLOCK,&new_mask,&old_mask) < 0)
printf("sigprocmask error\n");
alarm(usecs);
waitmask = old_mask;
sigdelset(&waitmask,SIGALRM);
if(sigsuspend(&waitmask) != -1)
printf("sigsuspend error\n");
uslept = alarm(0);
if(sigaction(SIGALRM,&old_act,NULL) < 0)
printf("sigaction(SIGARLM) old act error\n");
if(sigprocmask(SIG_SETMASK,&old_mask,NULL) < 0)
printf("sigprocmask set old mask error\n");
return uslept;
}
int main(void)
{
sleep(10);
return 0;
}
这个版本的sleep避免了早期实现中的竞争条件,但是仍未处理与以前设置的闹钟的交互作用,正如前面提到的,POSIX.1并未显式定义这些交互作用。
举例:
如先调用alarm(10),过了3秒再调用sleep(5),那将如何?假设sleep 5秒后返回,但是否在2s后又产生另一个SIGALRM信号呢?这些细节依赖于实现了。
阅读(917) | 评论(0) | 转发(0) |