1.信号
信号 是进程间通信的一种方式,这种方式没有传输数据
在内核中传递的是一个信号(整数) 信号的表示是一个整数
不同的信号值 代表不同含义
当然用户也可以自定义信号 既然是自定义的信号 那么含义也有程序员来解释
Terminate 终止
Signal Value Action Comment
────────────────────────────────────────────────────────
SIGHUP 1 Term Hangup detected on controlling terminal
or death of controlling process
控制终端的挂起操作,或者控制进程死亡时
控制终端上的所有进程都会收到SIGHUP信号SIGINT 2 Term Interrupt from keyboard
从键盘上收到中断信号 CTRL + CCore 输出信号 然后终止
SIGQUIT 3 Core Quit from keyboard
退出信号 CTRL + ZSIGILL 4 Core Illegal Instruction
非法指令SIGABRT 6 Core Abort signal from abort(3)
调用 abort这个函数 进程会受到这个信号SIGFPE 8 Core Floating-point exception
浮点运算异常机会产生这个信号SIGKILL 9 Term Kill signal
SIGSTOP 17,19,23 Stop Stop process
程序员自定义的信号SIGSEGV 11 Core Invalid memory reference
内存的非法引用 就会SIGSEGV信号
段错误
SIGPIPE 13 Term Broken pipe: write to pipe with no
readers; see pipe(7)
管道只有写数据端 没有读数据端的时候就会产生这个信号SIGALRM 14 Term Timer signal from alarm(2)
定时信号,在进程调用alarm时
超时产生这个信号 你定的闹钟时间到了 就会给你发这个信号
SIGTERM 15 Term Termination signal
SIGUSR1 30,10,16 Term User-defined signal 1
SIGUSR2 31,12,17 Term User-defined signal 2
SIGCHLD 20,17,18 Ign Child stopped or terminated
子进程停止或者中止时父进程会收到这个信号
SIGCONT 19,18,25 Cont Continue if stopped
SIGTSTP 18,20,24 Stop Stop typed at terminal
SIGTTIN 21,21,26 Stop Terminal input for background process
SIGTTOU 22,22,27 Stop Terminal output for background process
进程在收到一个信号时 通常会有三种处理方式
(1)默认行为
term Core收到一个信号时 采用操作系统的默认行为。
大部分信号的默认行为时把进程给干掉
只有一个SIGCHLD被忽略
(2)捕捉该信号
把一个信号跟用户自定义的信号处理函数关联
收到该信号的时 去执行关联的信号处理函数
(3)忽略该信号
2.信号的处理过程
通过 软件中断/软中断 去实现
信号处理函数其实是在 中断上下文执行
信号处理函数 -》 软中断函数
//写信号处理函数 是线程安全的/可重入
中断上下文 就是中断环境下 中断模式
3. linux下信号相关的API函数
(1)发送信号
kill
NAME
kill - send signal to a processSYNOPSIS
#include <sys/types.h>
#include <signal.h>
kill可以发送一个信号给一个指定的进程或多个进程
int kill(pid_t pid, int sig);
pid_t pid:
pid > 0: pid表示信号接收者的进程
pid = 0; 发送信号给调用进程同组的所有进程
pid = -1 发送信号给所有进程
pid < -1 发送信号给组id等于pid绝对值的所有进程
int sig : 要发送的信号
返回值 成功(至少有一个进程接收到该信号) 返回0
失败返回-1 同时errno被设置
raise 发信号给自己
NAME
raise - send a signal to the callerSYNOPSIS
#include <signal.h>int raise(int sig);
raise(sig) <=>kill(getpid(),sig);
alarm
NAME
alarm - set an alarm clock for delivery of a signalSYNOPSIS
#include <unistd.h>unsigned int alarm(unsigned int seconds);
seconds 多少秒后 发送一个闹钟信号
0 表示取消闹钟
返回值
返回上一个闹钟的剩余时间
alarm(10);
alarm(20);///20秒中之后收到了闹钟信号
//前面的闹钟就被替换
每一个进程都有一个属于自己的闹钟,闹钟时间到了
进程就会收到一个SIGALRM的信号,同一时刻
一个进程只有一个闹钟生效
闹钟会在时间结束的时候给你发一个信号 SIGALRM 给本进程
大部分是信号的默认行为都是杀死这个进程
那么我们又不是都希望杀死它
那么怎么改变行为
(2) 捕捉信号 改变信号的处理方式
NAME
signal - ANSI C signal handlingSYNOPSIS
#include <signal.h>typedef void (*sighandler_t)(int);
sighandler_t是什么?
sighandler_t是一个函数指着的类型。它可以用来定义函数指针变量
sighandler_t signal(int signum, sighandler_t handler);
int signum: 你要改变哪一个信号的处理方式
sighandler_t handler:捕捉到这个信号后 要调用的那个函数
1.自定义函数
void (*sighandler_t)(int);
没有返回值 但是有一个int参数
这个参数是用来保存信号的值的
void MySignalHandler(int sig)
{
中间就是处理过程
}
2.SIG_DFL:default 采用系统默认的处理方式
3.SIG_IGN:忽略该信号
返回值
成功返回该信号的上一个处理方式 你上一次调用了那个函数
失败返回SIG_ERR 同时errno被设置
练习 我们的程序,通常可以被CTRL+C干掉
那么现在你牛逼了 你能不能写一个程序 让ctrl+C 干不掉它 顺便嘲讽一波
代码:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void MySignalHandler(int sig)
{
switch (sig)
{
case SIGINT:
printf("\n傻了吧,干不掉我\n");
break;
default:
break;
}
}
int main(int argc,char *argv[])
{
signal(SIGINT,MySignalHandler);
//int res = pause();
//printf("res = %d\n",res);
while (1);
}
///////////
输入 ctrl+C 会输出 printf 内的内容
输入 ctrl+Z 会退出程序
(3)等待信号的到来
pause 让进程停在哪里 等待某个信号的到来
直到收到了信号
NAME
pause - wait for signalSYNOPSIS
#include <unistd.h>int pause(void);
DESCRIPTION
pause() causes the calling process (or thread) to sleep until a signal is
delivered that either terminates the process or causes the invocation of a
signal-catching function.RETURN VALUE
pause() returns only when a signal was caught and the signal-catching func‐
tion returned. In this case, pause() returns -1, and errno is set to EINTR.

本文详细介绍了Linux系统中的信号处理机制,包括各种信号的意义、信号的处理方式及其相关API函数。信号作为进程间通信的一种方式,其处理机制对于理解系统运作至关重要。

被折叠的 条评论
为什么被折叠?



