12.linux中的信号


12.1.什么是信号
(1)信号是通信内容受限(int型数字)的1种异步通信机制;信号是当前进程对外通信的1种手段;信号的目的用来通信的;信号是异步的(类似硬件中断);信号本质上是操作系统事先定义好的int型数字编号。
(2)信号由谁发出;用户在终端按下按键(譬如用户按下Ctrl+c按键终止程序运行);硬件异常后由操作系统内核发出信号;用户使用kill命令向其它进程发出信号;某种软件条件满足后也会发出信号,如alarm闹钟时间到会产生SIGALARM信号,向1个读端已经关闭的管道write时会产生SIGPIPE信号。
(3)信号由谁处理并如何处理;忽略信号(收到信号直接丢弃);捕获信号(信号绑定了某个函数);默认处理(当前进程收到该信号后执行信号默认操作,一般是忽略或终止进程)。


12.2.常见信号介绍
(1)SIGINT(2-Ctrl+C时OS送给前台进程组中每个进程);SIGABRT(6-调用abort函数,进程异常终止);SIGPOLL/SIGIO(8-指示1个异步IO事件,在高级IO中提及);SIGKILL(9-杀死进程的终极办法,该信号无法被忽略);SIGSEGV(11-无效存储访问时OS发出该信号,提示段错误信息)。
(2)SIGPIPE(13-涉及管道和socket编程);SIGALARM(14-涉及alarm函数的实现);SIGTERM(15-kill命令发送的OS默认终止信号);SIGCHLD(17-子进程终止或停止时OS向其父进程发此信号)。SIGUSR1
(3)SIGUSR1(10-用户自定义信号,作用和意义由应用自己定义);SIGUSR2(12-用户自定义信号,作用和意义由应用自己定义)。
(4)信号定位在/usr/include/signal.h和/usr/include/i386-linux-gnu/bits/signum.h这两个头文件中。


12.3.进程对信号的处理
(1)默认处理+忽略处理+捕获处理;signal函数绑定某个捕获函数后,当信号发生后会自动执行绑定的捕获函数,并且把信号编号作为传参传给捕获函数;signal的返回值在出错时为SIG_ERR,绑定成功时返回旧的捕获函数;signal函数的优点-简单好用,捕获信号常用;缺点-无法简单直接得知之前设置的对信号的处理方法。
(2)sigaction函数比signal更具有可移植性,其使用方法的关键是2个sigaction指针;sigaction可以1次得到设置新捕获函数和获取旧的捕获函数(其实还可以单独设置新的捕获或者单独只获取旧的捕获函数),而signal函数必须在设置新的捕获函数的同时才获取旧的捕获函数。


12.4.alarm和pause函数
(1)alarm函数,内核以API形式提供的闹钟;内核在1个进程中只维持1个alarm闹钟,在首次调用alarm后会返回0,在第2次调用alarm后返回上次闹钟还剩下的秒数并重新注册alarm闹钟。
(2)pause函数,pause函数的作用就是让当前进程暂停运行,交出CPU给其它进程去执行,当前进程进入pause状态后当前进程会表现为卡住/阻塞住,退出pause状态当前进程需要被信号唤醒。


12.signal
/*
 * 公司:XXXX
 * 作者:Rston
 * 博客:http://blog.csdn.net/rston
 * GitHub:https://github.com/rston
 * 项目:linux中的信号
 * 功能:演示signal函数的简单使用。
 */
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>

typedef void (*sighandler_t)(int);

// ctrl+c信号捕捉函数
void signal_func(int sig)
{
    printf("I catch ctrl + c.\n");
}

int main(int argc, char **argv)
{
#if 1
    // 指定信号SIGINT为具体的signal_func处理函数
    sighandler_t ret = ((sighandler_t) -2);
    ret = signal(SIGINT, signal_func);
    if (SIG_ERR == ret)
    {
        perror("signal error");
        exit(-1);
    }
#endif

#if 0
    // 指定信号SIGINT为默认处理
    signal(SIGINT, SIG_DFL);            
#endif

#if 0   
    // 指定信号SIGINT为忽略处理
    signal(SIGINT, SIG_IGN);        
#endif  

    printf("before while(1).\n");
    while(1);
    printf("after while(1).\n");

    return 0;
}

12.sigaction_alarm_pause
/*
 * 公司:XXXX
 * 作者:Rston
 * 博客:http://blog.csdn.net/rston
 * GitHub:https://github.com/rston
 * 项目:linux中的信号
 * 功能:演示sigaction和alarm和pause函数的简单使用。
 */
#include <stdio.h>
#include <signal.h>
#include <unistd.h> 

void mysleep(unsigned int seconds);

#if 1
void signal_func(int sig)
{

}
#endif

#if 0
void signal_func(int sig)
{
    printf("alarm happened.\n");
}
#endif

int main(int argc, char **argv)
{
#if 0
    int ret = -1;
    struct sigaction act = {0};
    act.sa_handler = signal_func;

    ret = sigaction(SIGALRM, &act, NULL);

    ret = alarm(5);
    printf("1st, ret = %d.\n", ret);    // 1st, ret = 0.
    sleep(3);

    ret = alarm(5);     
    printf("2st, ret = %d.\n", ret);    // 2st, ret = 2.
    sleep(1);

    ret = alarm(5);
    printf("3st, ret = %d.\n", ret);    // 3st, ret = 4.

#if 0
    while (1);
#endif

#if 1
    pause();
#endif
#endif

#if 1
    // 使用alarm和pause来模拟sleep
    printf("before mysleep.\n");
    mysleep(3);
    printf("after mysleep.\n");
#endif

    return 0;
}

#if 0
void mysleep(unsigned int seconds)
{
    struct sigaction act = {0};

    act.sa_handler = signal_func;
    sigaction(SIGALRM, &act, NULL);

    alarm(seconds);
    pause();
}
#endif

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值