文章目录

    • 信号
      • 常见信号
      • 信号定时函数
      • 信号捕捉函数
      • 信号集

信号

  • 信号是向进程传递消息的一种机制,发生事件时通过信号向进程进行通知,从而改变进程的行为,信号在软件层次上模拟中断,也叫软件中断,处理优先级较高
  • 对于前台进程可以通过特殊的字符发送信号,例如Ctrl+C即给当前进程发送一个SIGINT中断信号。
  • kill命令也是向进程发送信号,可以通过kill -l查询信号,例如kill -9 pid即向pid进程发送终止信号
  • 信号通信较为简单、不能携带大量的信息、优先级较高
  • 信号集有阻塞信号集和未决信号集,通过位视图标识,阻塞信号是指阻止信号被处理,未决是一种状态指的是从信号产生到信号处理的这段时间,先查询未决再查询阻塞。
  • 信号的默认处理动作为:Term终止进程、lgn忽略信号、Core终止进程并生成Core文件默认大小为0,可以通过ulimit -a查看,并通过ulimit -c unlimited进行大小修改即可看到相应文件,一般和gdb配合使用在gdb中可以通过core-file core查看文件、Stop暂定进程、Cont继续执行被暂停的进程,man 7 signal可查询详细信息

常见信号

信号代号信号名称说 明默认动作
1SIGHUP该信号让进程立即关闭,然后重新读取配置文件之后重启终止进程
2SIGINT程序中止信号,用于中止前台进程。相当于输出 Ctrl+C 快捷键终止进程
3SIGQUIT和SIGINT类似, 但由QUIT字符(通常是Ctrl+/)来控制。 进程在因收到SIGQUIT退出时会产生core文件, 在这个意义上类似于一个程序错误信号。终止进程
8SIGFPE在发生致命的算术运算错误时发出。不仅包括浮点运算错误,还包括溢出及除数为 0 等其他所有的算术运算错误终止进程、产生core文件
9SIGKILL用来立即结束程序的运行。本信号不能被阻塞、处理和忽略。般用于强制中止进程终止进程–强制
11SIGSEGV试图访问未分配给自己的内存, 或试图往没有写权限的内存地址写数据,段错误终止进程产生core文件
13SIGPIPE管道破裂。这个信号通常在进程间通信产生,比如采用FIFO(管道)通信的两个进程,读管道没打开或者意外终止就往管道写,写进程会收到SIGPIPE信号。终止进程
14SIGALRM时钟定时信号,计算的是实际的时间或时钟时间。alarm 函数使用该信号终止进程
15SIGTERM正常结束进程的信号,kill 命令的默认信号。如果进程已经发生了问题,那么这个信号是无法正常中止进程的,这时我们才会尝试 SIGKILL 信号,也就是信号 9终止进程
17SIGCHLD子进程结束时, 父进程会收到这个信号。忽略信号
18SIGCONT该信号可以让暂停的进程恢复执行。本信号不能被阻断继续/忽略
19SIGSTOP该信号可以暂停前台进程,相当于输入 Ctrl+Z 快捷键。本信号不能被阻断终止进程

信号定时函数

#include 

1. unsigned int alarm(unsigned int seconds);
//alarm不阻塞,程序正常执行,在指定的时间后向进程发送一个信号,通常是SIGALRM信号。
//参数seconds:指定多少秒后发送SIGALRM信号给调用进程。如果seconds为0,则取消任何现有的闹钟(如果有的话)。
//返回值:如果之前已有闹钟设置,该函数返回剩余的秒数并从新设置的秒数计时,如果没有设置过闹钟,返回0。
//SIGALRM:默认终止当前进程

#include 

2. int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue);
//成功时返回0,出错时返回-1,并设置errno
//周期性定时可代替alarm
//which:指定要设置的计时器类型,一般为ITIMER_REAL真实时间返回SIGALRM
//value:指向一个itimerval结构的指针
struct itimerval {
   struct timeval it_interval; /* 下一次间隔 */
    struct timeval it_value;   /* 多长时间开始计时 */
};
struct timeval{
    time_t tv_sec;//秒数
    suseconds_t tv_usec;//微秒
}
ovalue(可选):指向一个itimerval结构的指针,用来存储之前设置的定时器值。如果不需要旧值,可以传入NULL。

struct itimerval new_value;
//设置间隔
new_value.it_interval.tv_sec=2;
new_value.it_interval.tv_usec=0;

//设置延迟
new_value.it_value.tv_sec=3;
new_value.it_value.tv_usec=0;

//使用
 if (setitimer(ITIMER_REAL, &new_value, NULL) == -1) {
        perror("setitimer error");
        return 1;
    }

信号捕捉函数

#include 

1. typedef void (*sighandler_t)(int);//函数指针,输入int返回void
sighandler_t signal(int signum, sighandler_t handler);

//成功情况下,返回以前的信号处理函数指针。
//signum:要处理的信号编号,如SIGINT(2,对应Ctrl+C中断)、SIGTERM(15,程序终止信号)等。
//handler:处理函数指针。可以是以下几种情况之一:
/*
SIG_DFL:恢复信号的默认处理行为。
SIG_IGN:忽略该信号。
自定义函数指针:当进程接收到signum信号时,将调用此函数.
*/

//具体使用
void myalarm(int num){
    std::cout<<"捕捉的信号编号为"<<num<<std::endl;
}
signal(SIGALRM,myalarm);
alarm(3);



2. int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
//成功时返回0,失败时返回-1,并设置errno
//signum:要处理的信号编号。
//act:指向struct sigaction结构的指针,用于设置新的信号处理行为。该结构定义如下:
struct sigaction {
    void (*sa_handler)(int);  // 信号处理函数指针,捕捉后的处理函数
    void (*sa_sigaction)(int, siginfo_t *, void *); // 更高级的信号处理函数指针,支持传递附加信息
    sigset_t sa_mask;// 处理信号时临时阻塞的信号集
    int sa_flags;// 控制信号处理的标志,如SA_RESTART, SA_NODEFER等
    void (*sa_restorer)(void); // 仅供系统内部使用,通常设为NULL
};
//oldact通常设为NULL


//具体使用
void myalarm(int num){
    std::cout<<"捕捉的信号编号为"<<num<<std::endl;
}
struct sigaction act;
act.sa_flags=0;
act.sa_handler=myalarm;
sigemptyset(&act.sa_mask);//清空阻塞集

sigaction(SIGALRM,&act,NULL);
alarm(3);

信号集

  • 信号集有阻塞信号集和未决信号集,通过位视图标识,阻塞信号是指阻止信号被处理,未决是一种状态指的是从信号产生到信号处理的这段时间,先查询未决再查询阻塞。
#include 

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
//设置内核信号,包括阻塞、接触阻塞、替换
//成功时返回0,失败时返回-1,并设置errno。
//how:决定如何对内核阻塞信号集处理,可以是以下值之一:
/*
SIG_BLOCK:将set指定的信号集所包含的信号添加到当前的阻塞信号集中。
SIG_UNBLOCK:从当前的阻塞信号集中移除set指定的信号。
SIG_SETMASK:将当前的阻塞信号集设置为set指定的信号集,完全替换原有集合。
*/
//set:指向一个sigset_t类型的指针,表示要修改的信号集合。具体操作根据how参数决定。
//oldset一般为NULL


int sigpending(sigset_t *set);
//查询当前进程中哪些信号是未决的,不会清除未决信号的状态。
//成功时返回0。出错时返回-1,并设置errno。
//set:指向sigset_t类型的指针,用来存放查询结果。函数执行成功后,set中将包含当前进程所有未决信号的集合。


//具体使用
sigset_t set;//创建自定义信号集
sigemptyset(&set);//初始化
sigaddset(&set,SIGQUIT)
sigaddset(&set,SIGINT)//信号集中加入SIGQUIT、SIGINT信号,位视图法,将相应信号位置1

sigprocmask(SIG_BLOCK,&set,NULL)//将内核中相应的信号阻塞,位视图法,将相应信号位置1
sigpending(&set)//查询哪些信号是未决的
本站无任何商业行为
个人在线分享 » 【Linux】多进程基础–信号
E-->