信号(Signal)
在 Linux 系统中,信号(Signal) 是一种用于进程间通信的机制,它允许操作系统和进程之间传递通知,告知进程发生了某些事件。信号通常由内核生成,或者由其他进程发送。
信号的基本概念
信号是一种异步通知,它会中断正在运行的进程,并对其进行某种处理。信号机制是多进程环境下的一种重要通信手段,可以用于控制进程的行为(如终止进程、暂停进程、重新加载配置等)。
常见的信号
| 信号名称 | 信号编号 | 描述 |
|---|---|---|
SIGHUP |
1 | 终端挂起,通常用于通知进程重新加载配置。 |
SIGINT |
2 | 中断信号,通常由 Ctrl+C 触发,终止正在运行的进程。 |
SIGQUIT |
3 | 退出信号,通常由 Ctrl+\ 触发,进程退出并产生核心转储文件。 |
SIGILL |
4 | 非法指令,进程试图执行无效或非法的机器指令。 |
SIGABRT |
6 | 异常终止信号,进程调用 abort() 函数时触发。 |
SIGFPE |
8 | 浮点运算错误,例如除以零。 |
SIGKILL |
9 | 强制终止进程,无法被捕获或忽略。 |
SIGSEGV |
11 | 段错误,通常是由于非法访问内存(如访问已释放的内存)引起的。 |
SIGPIPE |
13 | 管道破裂,当向一个没有读端的管道写数据时会触发。 |
SIGALRM |
14 | 定时器信号,通常由 alarm() 函数设置的定时器触发。 |
SIGTERM |
15 | 终止信号,默认的终止进程信号,进程可以捕获并做清理操作。 |
SIGUSR1 |
10 | 用户定义信号 1,可以被应用程序使用来执行自定义操作。 |
SIGUSR2 |
12 | 用户定义信号 2,通常被应用程序用于自定义处理。 |
SIGCHLD |
17 | 子进程终止信号,父进程会接收到此信号以响应子进程的退出。 |
SIGSTOP |
19 | 停止信号,暂停进程的执行,无法被捕获或忽略。 |
SIGCONT |
18 | 继续执行信号,用于恢复被暂停的进程。 |
信号的处理
- 默认行为:
- 每个信号都有一个默认行为。例如,
SIGTERM默认终止进程,SIGSTOP默认暂停进程。
- 每个信号都有一个默认行为。例如,
- 信号的捕获:
- 进程可以通过设置信号处理程序来捕获并处理某些信号。进程可以决定是忽略信号,还是执行自定义的操作。
- 信号的阻塞与解除阻塞:
- 进程可以选择阻塞某些信号,避免信号在进程执行过程中中断。阻塞信号后,信号会在进程解除阻塞时传递。
信号的发送
信号可以通过以下几种方式发送:
-
由操作系统自动发送:
- 例如,
SIGSEGV是因为访问非法内存地址而自动发送的。
- 例如,
-
由其他进程通过系统调用发送:
- 使用
kill()系统调用,可以发送信号到指定的进程。例如: kill()命令发送的信号不仅限于SIGTERM,你也可以指定其他信号。
- 使用
-
由程序通过函数发送:
- 使用
raise()或kill()函数,程序可以发送信号到自身或其他进程:
- 使用
信号的捕获与处理
进程可以捕获并处理信号。可以使用 signal() 函数来指定处理某个信号的函数。处理信号的函数称为 信号处理程序。
示例:捕获 SIGINT 信号
在这个例子中,当按下 Ctrl+C(发送 SIGINT 信号)时,程序将捕获到信号并执行 handle_sigint() 函数。
注意:
- 在现代的 Linux 系统中,使用
sigaction()比signal()更为推荐,因为它更为强大和灵活。
信号的阻塞与解除阻塞
可以使用 sigprocmask() 函数来阻塞或解除阻塞信号。例如,阻塞 SIGINT 信号:
常用的信号操作函数
signal(): 设置信号处理函数。sigaction(): 设置更详细的信号处理规则(推荐使用)。raise(): 发送信号到当前进程。kill(): 向其他进程发送信号。sigprocmask(): 控制信号的阻塞与解除。sigpending(): 检查哪些信号已被发送但尚未处理。sigwait(): 等待一个或多个信号的发生。
总结
- 信号是 Linux 系统中一种重要的进程间通信和控制机制。
- 它可以用于通知进程发生了某些事件(例如终止、暂停、错误等)。
- 可以通过
signal()或sigaction()函数来捕获和处理信号。 - 信号也可以被阻塞、忽略或发送到其他进程。
- 理解信号机制对于编写健壮的多进程应用非常重要,尤其是在系统级编程中。
浙公网安备 33010602011771号