时钟信号 SIGALRM ,signal()函数 ,setitimer()函数,pause()函数应用

    xiaoxiao2025-10-12  8

    /**   * @file demo5.c  * @Synopsis  由软件条件产生信号  *   *  * 时钟信号(SIGALRM)  * 当内核检测到某种软件发生时也可以通过信号通知进程  *   * 例如闹钟超时产生 该信号;  *   * #include <unistd.h>  * unsigned int alarm(unsigned int seconds);  * @param unsigned int seconds 接收秒数  * @return unsigned int   * 反回值是0,或者是以前设定的闹钟时间还余下的秒数。  * 打个比方,某人要小睡一觉,设定闹钟为30分钟之后响,20分钟后被人吵醒,  * 还想多睡一会儿,于是重新设定闹钟为15分钟之后响,"以前设定的闹钟时间还余  * 下的时间"就是10分钟,如果seconds 值为0,表未闻对酒当歌以前设定的闹钟,函数的  * 返回值仍然是以前设定的闹钟时间还余下的秒数.  * 调用alarm 可以设定一个闹钟,也就是告诉内核在seconds 秒之后给当  * 前里程发SIGALRM   信号,该信号的默认处理动作是终止当前进程。  *  * @author MrClimb  * @version 1.1.0  * @date 2012-05-21  */ #include <stdio.h> #include <unistd.h> #include <sys/time.h> #include <signal.h> #include <stdlib.h>

    /* *************************************************************** */ /**  * @Synopsis  alarm()测式5秒后停止该进程  */ /* *************************************************************** */ void test1() {     int counter;         unsigned int senconds = alarm(5);     printf("5秒后停止计数\n");     for(counter=1;;counter++)     {         printf("counter = %d\n",counter);     }     printf(" 这一行没有被执行,则被信号终止了。否则。。。");      /*!*      * test       * Ctrl-C & Ctrl-'\' 当从键盘按下这个个快捷键时立即终止进程,而没有等待      * alarm 去发送信号SIGALRM      * 默认情况下当过了5秒之后 alarm 内部将发送信号 SIGALRM 停止进程      *       * ? 这里发送终止进程交给内核来终止吗!      */ }

    /* *************************************************************** */ /**  * @Synopsis  程序挂起  * int pause(void);  * pause 使调用进程挂起,直到有信号递达。  * 如果信号的处理动作是终止进程,则进程终止,pause 函数没有机会返回,  * 如果信号的处理动作是忽略,则进程处于挂起状态,pause 不返回;  * 如果信号的处理动作是捕捉,则调用了信号处理函数之后pause 返回 -1,errno 设置为EINTR,所以pause 只有出错的返回值  * 错误码 EINTR 表示" 被信号中断"  *   * #include <signal.h>  *  typedef void (*sighandler_t)(int);  *  sighandler_t signal(int signum,sighandler_t handler);  *  signal 可以看成 红绿灯;  *  也就是说如果信号处理的动作是用户自定义函数,在信号递达时就调用这个函数  *  这称为捕捉信号。  *  这里当传的是signum某一信号,则执行调用 handler 所指向的函数指针  *    *  **************************  *  1:用户注册了SIGALRM 信号的处理函数 sighandler 。  *  2:当前正在执行main函数,这时发生中断或异常切换到内核态。  *  3:在中断处理完毕后要返回用户态的main函数之前检查到有信号SIGALRM 递达  *  4:内核决定返回用户态后不是恢复main函数的上下文继续执行,而是执行sighandler 函数,sighandler 和main函数使用不  *  同的堆栈空间,它们之间不存在调用和被调用的关糸,是两个独立的控制流程  *  5:sighandler 函数返回后自动执行特殊的糸统调用sigreturn 再次进入内核态。  *  6:如果没有新的信号要递达,这次再返回用户态就是恢复main函数的上下文继续执行了。  *  *  **************************  *  ?这里捕捉信号号 signal 后它不会作终止当前进程吗!,而test1则会终止当前进程呢。  */ /* *************************************************************** */ void test2() {      // 定义该函数     void wakeup(int);     printf("about to sleep for 4 seconds\n");     signal(SIGALRM,wakeup);// 这里是在 4秒后捕捉到 alarm 产生的 SIGALRM 信号     alarm(4);     // 当前进程挂起     pause();     printf("Morning so soon?(这里被执行了,说明信号没有终止程序)\n"); } void wakeup(int isignum) {      printf("起床啦!时间到了。(捕捉到信号了。。)\n"); } /* *************************************************************** */ /**  * @Synopsis  获得一个精确的定时。。  * 操作糸统提供三种时间:  * 使用命令: time ./a.out 生成三个时间  * real/user/sys 三个时间  * 用户时间、用户与内核切换时间。。  *    * int setitimer(int which,const struct itimerval *new_value,struct itimerval *old_value)  * 将new_value 指向的结构体设为计时器的当前值,如果old_value不是NULL,将返回计时器原有值。  *  * @param int which:间歇计时器类型,有三种选择  *  ITIMER_REAL    // 数值为0,计时器的值实时递减,发送的信号SIGALRM  *                    类似于alarm()当某个计数时间完了后就产生一个这样的信号  *  ITIMER_VIRTUAL // 数值为1,进程执行时递减计时器的值,发送的信号是SIGVTALRM   *                    进程在执行,进程在用户空间执行,计时用户空间进程时间,用完之后产生一个信号SIGVTALRM  *  ITIMER_PROF    // 数值为2,进程和糸统执行都递减计时器的值,发送的信号是SIGPROF.  *  用户时间加上切换时间,一个进程要三个时间,那么十个进程,就得几百个时钟了,  *  那么怎么处理呢。物理时钟只有一个,这里物理时钟进行递减,那么其它进程时钟也作相应自减,  *  直到其它进程减到0为止,则发送信号。  *  *  struct itimerval{  *      struct timeval it_interval;// next value;计时器重启的间歇值  *      struct timeval it_value;// current value;计时器安装后首先启动的初始值  *  }  *  struct timeval{  *      long tv_sec;// seconds  *      long tv_usec;// microseconds (1/1000000)  *  }  *  @return success is returned value zero  *          failure is returned value -1 errno will be set 某个值  *          EFAULT : new_value or old_value  *          EINVAL : 其值不是 ITIMER_REAL,ITIMER_VIRTUAL OR ITIMER_PROF之一  *  */  /* *************************************************************** */ int set_ticker(int n_msecs) {     // 这里用两个时间,一个是时间,一个是时间间隔。     struct itimerval new_timeset;     long n_sec;// 秒     long n_usecs;// 微秒     n_sec = n_msecs/1000;     n_usecs = (n_msecs % 1000) * 1000L;

        new_timeset.it_interval.tv_sec = n_sec;     new_timeset.it_interval.tv_usec = n_usecs;

        new_timeset.it_value.tv_sec = n_sec;     new_timeset.it_value.tv_usec = n_usecs;

        return setitimer(ITIMER_REAL,&new_timeset,NULL); } void countdown(int signum) {       static int num = 10;     printf("%d..",num--);     fflush(stdout);// 强制输出缓冲区     if(num < 0)     {         printf("DONE!\n");         exit(0);     } } void test3() {         void countdown(int);         signal(SIGALRM,countdown);// 当捕捉到信号 SIGALRM 将执行 countdown 函数 下面 while 函数仍旧不断的循环。。         if(set_ticker(1000) == -1)         {             perror("set_ticker");         }else         {             while(1)             {                 pause();// 进程 永远 挂起             }         } } int main(int argc, char **argv) { #if 0     test1(); #endif #if 0     test2(); #endif #if 1     test3(); #endif

        return 0; }

    转载请注明原文地址: https://ju.6miu.com/read-1303071.html
    最新回复(0)