信号的发送和捕捉函数(alarm、kill、raise、pause、 sleep、abort)

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信号注册函数。

2. kill函数

(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

3. raise函数

与kill函数不同的是,raise函数运行是向进程自身发送信号。

              raise(向自己发送信号)

所需头文件

#include

#include

函数说明

向自己发送信号

函数原型

int raise(int sig)

函数传入值

sig:信号

函数返回值

成功:0

出错:-1,错误原因存于error中

4. pause函数

(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

5. sleep和abort

(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

 

6.  信号的发送与捕捉简要总结

对上述信号的发生与捕捉函数简要总结说明如下:

kill函数可以向有用户权限的任何进程发送信号,通常用kill函数来结束进程。

与kill函数不同的是,raise函数只向进程自身发送信号。

使用alarm函数可以设置一个时间值(闹铃时间),在将来的某个时刻该时间值超过时发送信号。

pause函数使调用进程挂起直至捕捉到一个信号。

 

摘录自《深入浅出Linux工具与编程》

 

  

你可能感兴趣的:(Linux进程间通信)