linux中的两个很重要的信号:SIGALRM信号和SIGCHID信号

Linux定时函数介绍:

http://www.cnblogs.com/wenqiang/p/5525261.html

 

Linux下实现定时器Timer的几种方法总结

https://www.jb51.net/article/96052.htm

 

linux的定时器(timer_create,timer_gettime,timer_delete,SIGEV_SIGNAL)

http://blog.chinaunix.net/uid-28458801-id-5035347.html

 

Linux下实现定时器Timer的几种方法总结

https://www.jb51.net/article/96052.htm

 

linux中的两个很重要的信号:SIGALRM信号和SIGCHID信号

https://www.cnblogs.com/yxysuanfa/p/6782474.html

 

 

在进行堵塞式系统调用时。为避免进程陷入无限期的等待,能够为这些堵塞式系统调用设置定时器。Linux提供了alarm系统调用和SIGALRM信号实现这个功能。

        要使用定时器。首先要安装SIGALRM信号。假设不安装SIGALRM信号,则进程收到SIGALRM信号后。缺省的动作就是终止当前进程。

 

SIGALRM信号成功安装后,在什么情况下进程会收到该信号呢?这就要依赖于Linux提供的定时器功能。在Linux系统下,每一个进程都有惟一的一个定时器,该定时器提供了以秒为单位的定时功能。在定时器设置的超时时间到达后,调用alarm的进程将收到SIGALRM信号。

alarm系统调用的原型为:

#include <unistd.h>

unsigned int alarm(unsigned int seconds);

參数说明:

1)seconds:要设定的定时时间,以秒为单位。在alarm调用成功后開始计时。超过该时间将触发SIGALRM信号。

返回值:

返回当前进程曾经设置的定时器剩余秒数。

 

 

 

例8-10:编程利用SIGALRM信号实现秒定时器。

代码例如以下:

#include <stdio.h>

#include <signal.h>

//全局计数器变量

int Cnt=0;

//SIGALRM信号处理函数

void CbSigAlrm(int signo)

{

//输出定时提示信息

printf("   seconds: %d",++Cnt);

printf("\r");

//又一次启动定时器,实现1秒定时

alarm(1);

}

void main()

{

//安装SIGALRM信号

if(signal(SIGALRM,CbSigAlrm)==SIG_ERR)

{

perror("signal");

return;

}

//关闭标准输出的行缓存模式

setbuf(stdout,NULL);

//启动定时器

alarm(1);

//进程进入无限循环,仅仅能手动终止

while(1)

{

//暂停,等待信号

pause();

}

}

 

8.5.2 SIGCLD信号

        在Linux的多进程编程中,SIGCLD是一个很重要的信号。当一个子进程退出时。并非马上释放其占用的资源,而是通知其父进程,由父进程进行兴许的工作。

 

在这一过程中,系统将依次产生下列事件。

1)向父进程发送SIGCLD信号,子进程进入zombie(僵尸)状态。

2)父进程接收到SIGCLD信号,进行处理。

        假设在上述过程中父进程既没有忽略SIGCLD信号。也未捕获该信号进行处理,则子进程将进入僵尸状态。僵尸状态的进程不能被操作系统调用,也没有不论什么可执行代码,它只是是占用了进程列表中的一个位置而已。

 

假设仅有几个僵尸进程不会影响系统的执行,可是假设僵尸进程过多。则将会严重影响系统的执行。因此,在编程过程中应避免产生僵尸进程。有两种主要的处理方法能够避免产生僵尸进程:一是父进程忽略SIGCLD信号;二是父进程捕获SIGCLD信号,在信号处理函数中获取子进程的退出状态。忽略信号的方式比較简单。仅仅须要调用signal(SIGCLD,SIG_IGN)语句就可以完毕。假设要捕获信号并处理。那么先要安装SIGCLD信号,然后在信号处理函数中调用wait或者waitpid等函数获取子进程的退出状态。

 

例8-11:编程捕获SIGCLD信号。输出各子进程的ID和退出状态码。

 

 

代码例如以下:

#include <stdio.h>

#include <stdlib.h>

#include <signal.h>

//SIGCLD信号处理函数

void CbSigCld(int signo)

{

//保存退出进程的ID

int pid;

//保存退出进程的退出状态码

int status;

//等待不论什么一个子进程退出

pid=waitpid(-1,&status,0);

//输出退出的子进程ID和退出代码

printf("Child process %d exit with status %d\n",pid,status);

}

void main()

{

int i,pid;

//安装SIGCLD信号

if(signal(SIGCLD,CbSigCld)==SIG_ERR)

{

perror("signal");

return;

}

//循环创建子进程

for(i=0;i<5;i++)

{

pid=fork();

//假设是子进程

if(pid==0)

{

//退出子进程,退出状态码为0

exit(0);

}

//假设是父进程

else

{

sleep(1);

}

}

}

 

//SECOND---PART///

Linux定时函数介绍:

http://www.cnblogs.com/wenqiang/p/5525261.html

  在程序开发过程中,我们时不时要用到一些定时器,通常如果时间精度要求不高,可以使用sleep,uslepp函数让进程睡眠一段时间来实现定时,

前者单位为秒(s),后者为微妙(us);但有时候我们又不想让进程睡眠阻塞在哪儿,我们需要进程正常执行,当到达规定的时间时再去执行相应的操作,

在linux下面我们一般使用alarm函数跟setitimer函数来实现定时功能;

下面对这两个函数进行详细分析:

(1)alarm函数

  alarm也称为闹钟函数,它可以在进程中设置一个定时器,当定时器指定的时间到时,它向进程发送SIGALRM信号;

alarm函数原型如下:

1 unsigned int alarm(unsigned int seconds);
2 
3 //seconds 为指定的秒数

返回值:

成功:如果调用此alarm()前,进程已经设置了闹钟时间,则返回上一个闹钟时间的剩余时间,否则返回0。

出错:-1

下面是alarm()函数的简单例子:

复制代码

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <unistd.h>
 4 #include <signal.h>
 5 
 6 void func()
 7 {
 8     printf("this is func\n");
 9 }
10 
11 int main()
12 {
13 
14     signal(SIGALRM, func); //2s后要执行的函数
15     alarm(2);//设置定时2s
16 
17     while (1);
18 
19     return 0;
20 }

复制代码

(2)setitimer()函数

  在linux下如果对定时要求不太精确的话,使用alarm()和signal()就行了,但是如果想要实现精度较高的定时功能的话,就要使用setitimer函数。

  setitimer()为Linux的API,并非C语言的Standard Library,setitimer()有两个功能,一是指定一段时间后,才执行某个function,二是每间格一段时间就执行某个function;

  Linux为每个任务安排了3个内部定时器:

ITIMER_REAL:实时定时器,不管进程在何种模式下运行(甚至在进程被挂起时),它总在计数。定时到达,向进程发送SIGALRM信号。

ITIMER_VIRTUAL:这个不是实时定时器,当进程在用户模式(即程序执行时)计算进程执行的时间。定时到达后向该进程发送SIGVTALRM信号。 

ITIMER_PROF:进程在用户模式(即程序执行时)和核心模式(即进程调度用时)均计数。定时到达产生SIGPROF信号。ITIMER_PROF记录的时间比ITIMER_VIRTUAL多了进程调度所花的时间。

定时器在初始化是,被赋予一个初始值,随时间递减,递减至0后发出信号,同时恢复初始值。在任务中,我们可以一种或者全部三种定时器,但同一时刻同一类型的定时器只能使用一个。

setitimer函数原型如下:

复制代码

 1  #include <sys/time.h>
 2 
 3        int setitimer(int which, const struct itimerval *new_value,
 4                      struct itimerval *old_value);
 5 
 6  Timer values are defined by the following structures:
 7 
 8            struct itimerval {
 9                struct timeval it_interval; /* next value */
10                struct timeval it_value;    /* current value */
11            };
12 
13            struct timeval {
14                time_t      tv_sec;         /* seconds */
15                suseconds_t tv_usec;        /* microseconds */
16            };

复制代码

  it_interval用来指定每隔多长时间执行任务, it_value用来保存当前时间离执行任务还有多长时间。比如说, 你指定it_interval为2秒(微秒为0),开始的时候我们把it_value的时间也设定为2秒(微秒为0),当过了一秒, it_value就减少一个为1, 再过1秒,则it_value又减少1,变为0,这个时候发出信号(告诉用户时间到了,可以执行任务了),并且系统自动把it_value的时间重置为 it_interval的值,即2秒,再重新计数

下面是setitimer简单实例:

复制代码

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stdlib.h>
 4 #include <signal.h>
 5 #include <sys/time.h>
 6 
 7 void test_func()
 8 {
 9     static count = 0;
10 
11     printf("count is %d\n", count++);
12 }
13 
14 void init_sigaction()
15 {
16     struct sigaction act;
17           
18     act.sa_handler = test_func; //设置处理信号的函数
19     act.sa_flags  = 0;
20 
21     sigemptyset(&act.sa_mask);
22     sigaction(SIGPROF, &act, NULL);//时间到发送SIGROF信号
23 }
24 
25 void init_time()
26 {
27     struct itimerval val;
28          
29     val.it_value.tv_sec = 1; //1秒后启用定时器
30     val.it_value.tv_usec = 0;
31 
32     val.it_interval = val.it_value; //定时器间隔为1s
33 
34     setitimer(ITIMER_PROF, &val, NULL);
35 }
36 
37 int main(int argc, char **argv)
38 {
39 
40     init_sigaction();
41     init_time();
42 
43     while(1);
44 
45     return 0;
46 }

复制代码

可以看出每个一秒输出一个count的值:

下面是运行结果:

[root@localhost 5th]# ./test 
count is 0
count is 1
count is 2
count is 3
count is 4
count is 5
count is 6
count is 7
count is 8
count is 9

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值