1. alarm函数
(1) alarm函数原型
alarm(设置信号传送闹钟) |
|
所需头文件 |
#include #include |
函数说明 |
alarm()用来设置信号SIGALRM在经过参数seconds指定的秒数后传送给目前的进程。如果参数seconds 为0,则之前设置的闹钟会被取消,并将剩下的时间返回 |
函数原型 |
unsigned int alarm(unsigned int seconds) |
函数返回值 |
返回之前闹钟的剩余秒数,如果之前未设闹钟,则返回0 |
(2) alarm函数说明
当所设置的时间值超过后,产生SIGALRM信号。如果不忽略或不捕捉此信号,则其默认动作是终止该进程。
每个进程只能有一个闹钟时间。如果在调用alarm时,以前已为该进程设置过闹钟时间,而且它还没有超时,则该闹钟时间的剩余时间值作为本次alarm函数调用的值返回,以前登记的闹钟时间则被新值代换。
如果有以前登记的尚未超过的闹钟时间,而新设的闹钟时间值为0,则取消以前的闹钟时间,其剩余时间值仍作为函数的返回值。
(3) alarm函数举例
alarm.c 源代码如下:
#include
#include
#include
void handler() { /*信号处理函数*/
printf("hello\n");
}
int main()
{
int i;
int time ;
signal(SIGALRM,handler); /*注册SIGALRM信号处理方式*/
alarm(3);
for(i=1;i<5;i++){
printf("sleep %d ...\n", i);
sleep(1);
}
alarm(3);
sleep(2);
time=alarm(0) ; /*取消SIGALRM信号,返回剩余秒数*/
printf("time=%d\n",time) ;
for(i=1;i<3;i++){
printf("sleep %d ...\n", i);
sleep(1);
}
return 0 ;
}
编译 gcc alarm.c –o alarm。
执行./alarm,执行结果如下:
sleep 1 ...
sleep 2 ...
sleep 3 ...
hello
sleep 4 ...
time=1
sleep 1 ...
sleep 2 ...
对程序结果分析如下:
信号是一种软中断,中断的原理是保留执行现场,跳转到中断函数处执行,执行完后恢复以前的现场在断点处继续往下执行。所以alarm函数经过3秒时,for循环已经到了sleep的3秒位置;alarm发送闹铃信号,引起中断,程序执行SIGALRM注册函数handler(中断处理函数),即输出hello。信号处理handler函数执行完后,应用程序从中断点恢复,继续执行for循环,此时sleep到了4秒的位置。
alarm(0)取消注册的闹铃(SIGALRM)信号,所以,第二次没有执行SIGALRM信号注册函数。
(1) kill函数原型
kill函数是将信号发送给指定的pid进程。普通用户利用kill函数将信号发送给该用户下任意一个进程,而特权用户(root)可以将信号发送系统中的任意一个进程。
kill函数原型及说明如下:
kill(传送信号给指定的进程) |
||
所需头文件 |
#include #include |
|
函数说明 |
kill()可以用来传送参数sig指定的信号给参数pid指定的进程 |
|
函数原型 |
int kill(pid_t pid,int sig) |
|
函数传入值 |
pid |
pid>0 将信号传给进程识别码为pid 的进程 |
pid=0 将信号传给和目前进程相同进程组的所有进程 |
||
pid=-1 将信号广播传送给系统内所有的进程 |
||
pid<0将信号传给进程组识别码为pid绝对值的所有进程 |
||
sig |
信号编号 |
|
函数返回值 |
成功:0 |
|
出错:-1,错误原因存于error中 |
||
错误代码 |
EINVAL:参数sig不合法 ESRCH:参数pid 所指定的进程或进程组不存在 EPERM:权限不够无法传送信号给指定进程 |
(2) kill函数举例
下面代码实现的是父进程发信号给子进程。
kill.c 源代码如下:
#include
#include
#include
#include
#include
int main()
{
pid_t pid;
int status;
pid= fork() ;
if( 0==pid ){
printf("Hi I am child process!\n");
sleep(10);
}
else if ( pid > 0 ){
printf("send signal to child process (%d) \n",pid);
sleep(1);
/*发送SIGABRT信号给子进程,此信号引起接收进程异常终止*/
kill(pid ,SIGABRT);
/*等待子进程返回终止信息*/
wait(&status);
if(WIFSIGNALED(status))
printf("chile process receive signal %d\n",WTERMSIG(status));
}else{
perror("fork error") ;
return -1 ;
}
return 0 ;
}
编译 gcc kill.c –o kill。
执行./kill,执行结果如下:
Hi I am child process!
send signal to child process (10498)
chile process receive signal 6
与kill函数不同的是,raise函数运行是向进程自身发送信号。
raise(向自己发送信号) |
|
所需头文件 |
#include #include |
函数说明 |
向自己发送信号 |
函数原型 |
int raise(int sig) |
函数传入值 |
sig:信号 |
函数返回值 |
成功:0 |
出错:-1,错误原因存于error中 |
(1) pause函数原型
pause(让进程暂停直到信号出现) |
|
所需头文件 |
#include |
函数说明 |
令目前的进程暂停(进入睡眠状态),直到被信号(signal)所中断 |
函数原型 |
int pause(void) |
函数返回值 |
只返回-1,错误原因存于error中 |
错误代码 |
EINTR:有信号到达中断了此函数 |
(2) pause函数举例
下面pause.c源代码简单的实现了sleep函数的功能。由于SIGALRM信号默认的系统动作为终止进程,所以在程序调用pause之后就暂停,当3秒后接收到alarm信号时进程就终止。
pause.c源代码如下:
#include
#include
#include
int main()
{
int ret ;
ret=alarm(3) ; /*调用alarm定时器函数*/
pause() ;
printf("I have been waken up.\n") ;
return 0 ;
}
编译 gcc pause.c –o pause。
执行./pause,执行结果如下:
Alarm clock
(1) sleep函数原型
sleep(让进程暂停执行一段时间) |
|
所需头文件 |
#include |
函数说明 |
sleep()会令目前的进程暂停,直到达到参数seconds所指定的时间,或是被信号所中断 |
函数原型 |
unsigned int sleep(unsigned int seconds) |
函数传入值 |
seconds:睡眠的秒数 |
函数返回值 |
若进程暂停到参数seconds所指定的时间,则返回0;若有信号中断则返回剩余秒数 |
(2) abort函数原型
abort(以异常方式结束进程) |
|
所需头文件 |
#include |
函数说明 |
此函数将SIGABRT信号给调用进程,此信号将引起调用进程的异常终止。此时所有已打开的文件流会自动关闭,所有的缓冲区数据会自动写回。 |
函数原型 |
void abort(void) |
(3) sleep、abort函数举例
sys_sleep.c源代码如下:
#include
#include
int main(void)
{
system("pwd") ;
sleep(9) ; /*wait 9 second*/
printf("Calling abort()\n");
abort();
printf("abort() after\n") ;
return 0; /* This is never reached */
}
编译 gcc sys_sleep.c -o sys_sleep。
执行./sys_sleep,执行结果如下:
/home/zjkf/public/signal
Calling abort
对上述信号的发生与捕捉函数简要总结说明如下:
kill函数可以向有用户权限的任何进程发送信号,通常用kill函数来结束进程。
与kill函数不同的是,raise函数只向进程自身发送信号。
使用alarm函数可以设置一个时间值(闹铃时间),在将来的某个时刻该时间值超过时发送信号。
pause函数使调用进程挂起直至捕捉到一个信号。
摘录自《深入浅出Linux工具与编程》