C语言笔记-22-Linux基础-信号

C语言笔记-22-Linux基础-信号



前言

自学笔记,没有历史知识铺垫(省略百度部分)C语言笔记-22-Linux基础-信号


一、信号概括

软件中的中断信号,软中断、异常中断都是信号,中断机制,信号处理程序。

系统提供的中断信号

linux 64个,数量根据系统不同。此处展示mac中断信号

No    Name         Default Action       Description
1     SIGHUP       terminate process    terminal line hangup
2     SIGINT       terminate process    interrupt program
3     SIGQUIT      create core image    quit program
4     SIGILL       create core image    illegal instruction
5     SIGTRAP      create core image    trace trap
6     SIGABRT      create core image    abort program (formerly SIGIOT)
7     SIGEMT       create core image    emulate instruction executed
8     SIGFPE       create core image    floating-point exception
9     SIGKILL      terminate process    kill program
10    SIGBUS       create core image    bus error
11    SIGSEGV      create core image    segmentation violation
12    SIGSYS       create core image    non-existent system call invoked
13    SIGPIPE      terminate process    write on a pipe with no reader
14    SIGALRM      terminate process    real-time timer expired
15    SIGTERM      terminate process    software termination signal
16    SIGURG       discard signal       urgent condition present on socket
17    SIGSTOP      stop process         stop (cannot be caught or ignored)
18    SIGTSTP      stop process         stop signal generated from keyboard
19    SIGCONT      discard signal       continue after stop
20    SIGCHLD      discard signal       child status has changed
21    SIGTTIN      stop process         background read attempted from control terminal
22    SIGTTOU      stop process         background write attempted to control terminal
23    SIGIO        discard signal       I/O is possible on a descriptor (see fcntl(2))
24    SIGXCPU      terminate process    cpu time limit exceeded (see setrlimit(2))
25    SIGXFSZ      terminate process    file size limit exceeded (see setrlimit(2))
26    SIGVTALRM    terminate process    virtual time alarm (see setitimer(2))
27    SIGPROF      terminate process    profiling timer alarm (see setitimer(2))
28    SIGWINCH     discard signal       Window size change
29    SIGINFO      discard signal       status request from keyboard
30    SIGUSR1      terminate process    User defined signal 1
31    SIGUSR2      terminate process    User defined signal 2

信号的产生 > 信号的到达 > 信号的处理

  1. 未决信号:信号产生到处理的过程中,信号处于未决状态(未处理状态)

信号处理三种方法

  1. SIG_IGN 缺省处理 (大部分进程的缺省处理,都是终止当前进程,即信号2)
  2. SIG_DFL 忽略处理
  3. 用户自定义处理

二、信号函数

typedef void (*sig_t) (int);
改变进程的信号处理函数
sig_t signal(int sig, sig_t func);
入参

  1. sig 信号编号
  2. func 指定信号处理函数指针

返回值
错误:SIG_ERR errno被设置
成功:返回原来的信号处理函数指针

代码示例

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    signal(SIGINT, SIG_IGN);
    sleep(10);
    return 0;
}
// 执行结果 ctrl+c中断时,将无法生效
dony15$ ./main 
^C^C^C^C^C^C^C^C^C^C^C^C^C^C
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

void customHandle(int sig)
{
    printf("自定义函数执行%d\n", sig);
    return;
}
int main(int argc, char *argv[])
{
    signal(SIGINT, customHandle);
    sleep(10);
    return 0;
}

// ctrl+c中断时 执行结果
dony15$ ./main 
^C自定义函数执行2

// 终端使用kill发送信号时 执行结果 kill -2 16817
自定义函数执行2

三、信号的产生

  1. 硬件产生信号: ctrl+c ctrl+\
  2. 使用命令给进程发信号: kill -信号编号 进程pid
  3. 使用系统调用或库函数,向进程发送信号:
    3.1. kill() 给指定进程发送指定信号
    3.2. raise() 给当前进程发送信号
    3.3. alarm() 定时发送信号
    3.4. abort() 给自己发送异常终止信号
    3.5. setitimer() 设置定时器(闹钟)。可代替alarm函数。精度微妙us,可以实现周期定时。

alarm定时发送信号示例

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    alarm(1);
    for (int i = 0; i>=0; i++)
    {
        printf("i=%d \n",i);
    }
    return 0;
}

// 执行结果
i=0 
i=1 
i=2 
...
i=7031440 
i=7031441 

pause 阻塞线程

让当前进程、线程阻塞,等待信号,执行完信号处理函数后返回。
int pause(void);
固定返回 -1 errno被设置

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

void customHandle(int sig)
{
    printf("自定义函数执行%d\n", sig);
    return;
}
int main(int argc, char *argv[])
{
    signal(SIGINT, customHandle);
    int result= pause();
    perror("pause");
    return 0;
}

// 终端使用kill发送信号时 执行结果 kill -2 4687
pause: Interrupted system call
自定义函数执行2

四、信号掩码集和未决信号集

PCB中以数组形式,bit元素记录信号掩码集未决信号集,数组下标长度对应信号编码 如arr[0]对应SIGHUP

  1. 信号掩码集: 记录信号是否被阻塞,元素为1时,表示该下标对应信号被阻塞,0时标识未阻塞
  2. 未决信号集:记录信号是否未决,元素为1时,表示该下标对应信号未决,0时标识没有信号产生

在这里插入图片描述

  1. 同一数组下标(同一信号),掩码集=1 表示信号阻塞。此时对应数组下标的未决信号无论是0还是1,都无法执行。
  2. 同一数组下标(同一信号),掩码集=0 表示信号不阻塞。此时对应数组下标的未决信号=1时,表示信号到达即可执行。
  3. 同一数组下标(同一信号),掩码集=0 表示信号不阻塞。此时对应数组下标的未决信号=0时,表示没有信号。

五、设置阻塞信号

信号集类型相关操作

#include <signal.h>
// sigset_t 信号集类型
// 将传入的信号集初始化为空 0 sig empty set(set表示集,非设置的意思)。成功返回0 失败 -1 errorno
int sigemptyset(sigset_t *set);
// 将传入的信号集初始化为填满状态 1 sig fill set。 成功返回0 失败 -1 errorno
int sigfillset(sigset_t *set);
// 将信号添加到信号集中 sig add set。 成功返回0 失败 -1 errorno
int sigaddset(sigset_t *set, int signo);
// 将信号从信号集中移除 sig del set。 成功返回0 失败 -1 errorno
int sigdelset(sigset_t *set, int signo);
// 判断信号是否为信号集中的成员 sig is member。 真1 假0
int sigismember(const sigset_t *set, int signo);

示例代码


#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

int main(int argc, char *argv[])
{
    sigset_t set;
    sigemptyset(&set);
    sigaddset(&set, 1);
    sigaddset(&set, 2);
    int isMember = sigismember(&set, 2);
    isMember ? printf("Y\n") : printf("N\n");
    sigdelset(&set, 2);
    int isMember2 = sigismember(&set, 2);
    isMember2 ? printf("Y\n") : printf("N\n");
    return 0;
}
// 输出结果
Y
N

设置信号集到信号掩码集

// SIG_BLOCK 将传入信号集与原有信号集的并集,更新到信号掩码集。
// SIG_UNBLOCK 将传入信号集从原有信号集排除,更新到信号掩码集。
// SIG_SETMASK 保存传入信号集到信号掩码集,并覆盖与原有信号集交集部分。
// oset 原信号掩码集,NULL 丢弃原信号掩码集。
int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);
// 返回 0成功 -1失败 errorno

示例代码


#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

int main(int argc, char *argv[])
{
    sigset_t set;
    sigemptyset(&set);
    // 阻塞2号信号
    sigaddset(&set, 2);
    sigprocmask(SIG_SETMASK, &set, NULL);
    while (1);
    printf("end\n");
    return 0;
}

// 输出结果 尝试ctrl+c 触发2号信号,由于设置2号信号在信号掩码中阻塞,此时失效,尝试使用3号信号ctrl+$结束程序
dony15$ ./a.out 
^C^C^C^C^C^C^C^C^C^\Quit: 3

六、获取未决信号

总结

本章主要为C语言笔记-22-Linux基础-信号

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值