Chinaunix首页 | 论坛 | 博客
  • 博客访问: 557405
  • 博文数量: 142
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1452
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-12 16:28
文章分类

全部博文(142)

文章存档

2016年(10)

2015年(60)

2014年(72)

我的朋友

分类: C/C++

2014-08-27 15:37:45

一、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

点击(此处)折叠或打开

  1. #include <signal.h>
  2. #include <unistd.h>

  3. typedef void (*signal_handler)(int);

  4. signal_handler old_sig_handle;

  5. static void sig_alrm(int signo)
  6. {

  7. }

  8. unsigned int sleep1(unsigned int nsecs)
  9. {
  10.     if((old_sig_handle = signal(SIGALRM,sig_alrm)) == SIG_ERR)
  11.         return nsecs;
  12.     alarm(nsecs);
  13.     pause();
  14.     signal(SIGALRM,old_sig_handle);
  15.     return (alarm(0));
  16. }

  17. int main(void)
  18. {
  19.     printf("before sleep1......\n");
  20.     sleep1(5);
  21.     printf("after sleep1.......\n");
  22.     return 0;
  23. }


点击(此处)折叠或打开

  1. #include <setjmp.h>
  2. #include <unistd.h>
  3. #include <signal.h>

  4. static jmp_buf env_alrm;


  5. static void sig_alrm(int signo)
  6. {
  7.     longjmp(env_alrm,1);
  8. }

  9. unsigned int sleep2(unsigned int nsecs)
  10. {
  11.     if(signal(SIGALRM,sig_alrm) == SIG_ERR)
  12.         return nsecs;

  13.     if(setjmp(env_alrm) == 0) {
  14.         alarm(5);
  15.         pause();
  16.     }

  17.     return(alarm(0));
  18. }

  19. static void sig_int(int signo)
  20. {
  21.     int i,j;
  22.     volatile int k;

  23.     printf("\nsig_int starting\n");
  24.     for(i = 0 ;i < 300000; i++)  //这段代码的作用主要是产生大于5s的计算,使得此信号处理函数处理时间大于sleep时间
  25.         for(j = 0; i < 4000; j++)
  26.             k += i*j;
  27.     printf("sig_int finished\n");
  28. }

  29. int main()
  30. {
  31.     unsigned int unslept;

  32.     if(signal(SIGINT,sig_int) == SIG_ERR)
  33.         perror("signal(SIGINI) error");
  34.     unslept = sleep2(5);
  35.     printf("sleep2 returned: %u\n",unslept);
  36.     exit(0);
  37. }
运行./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信号呢?这些细节依赖于实现了。

阅读(914) | 评论(0) | 转发(0) |
0

上一篇:中断的系统调用

下一篇:longjmp & setjmp

给主人留下些什么吧!~~