Linux进程间通信(四)---信号通信之信号发送捕捉kill()、raise()、alarm()、pause()及其基础实验

/*********************************************************************

* 2019年6月26日声明:本博客资源下载积分最开始为免费的,我也不知道为什么有的很高了。

*如果有问题加我微信:wensong2048,(加我备注来源以及需求,否则不通过,谢谢)

*********************************************************************/

信号概述

   ●  信号是在软件层次上对中断机制的一种模拟。在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。

   ●  信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上进程也不知道信号到底什么时候到达。

   ●  信号可以直接进行用户空间进程和内核进程之间的交互,内核进程也可以利用它来通知用户空间进程发生了哪些系统事件。它可以在任何时候发给某一个进程,而无需知道该进程的状态。如果该信号当前并未处于执行态(Running),则该信号由内核保存起来,直到该进程恢复执行再传递给它为止。如果一个信号被进程设置为阻塞,则该信号的传递被延迟,直到其阻塞被取消时才被传递给进程。

   ●  信号是进程间通信机制中唯一的异步通信机制,可以看作是异步通知,通知接收信号的进程有哪些事件发生了。信号机制除了基本通知外,还可以传递附加信息。

信号来源

     信号事件发生的来源有两种:

     ① 硬件来源。如我们按下了键盘上的按钮 或者出现其他硬件故障;

     ② 软件来源。最常用发送信号的系统函数有kill()、raise()、alarm()、setitimer()和sigqueue()等,软件来源还包括一些非法运算等操作。

进程响应信号的方式

    ① 忽略信号。忽略信号即对信号不做处理,其中,有两个信号不能忽略:SIGKILL和SIGSTOP。

    ② 捕捉信号。定义信号处理函数,当信号发生时,执行响应的处理函数。

    ③ 执行默认操作。Linux对每种信号都规定了默认操作,如下表所示:

   

 

信号的生命周期

     一个完整的信号生命周期可以分为3个重要阶段,这3个阶段由4个重要事件来刻画的;信号产生、信号在进程中注册、信号在进程中注销、执行信号处理函数。这里信号的产生、注册、注销等是指信号的内部实现机制,而不是信号的函数实现(不受我们的掌控)。因此信号注册与否与后面讲到的发送信号函数(如 kill()等)及信号安装函数(如 signal()等)无关,只与信号值有关。

   相邻两个事件的时间间隔构成信号生命周期的一个阶段,如下图1.注意这里的信号处理有多种方式,一般是由内核完成的,当然也可以由用户进程来完成。

   

    信号的处理包括信号的发送、捕捉和处理,它们有各自相对应的常见函数:

    ●  发生信号的函数: kill()、raise()。 

    ●  捕捉信号的函数: alarm()、pause()。

    ●  处理信号的函数: signal()、sigaction()。

  本节主要讲信号的发送与捕捉,下一节再讲处理

信号发送函数 kill()和raise()

函数说明

   kill()函数同咱们的kill系统命令一样(但不能误以为kill()就是kill哈),可以发送信号给进程或进程组(实际上,kill系统命令只是kill()函数的一个用户接口)。这里需要注意的是,kill()函数不仅可以终止进程(实际上是通过发出SIGKILL信号终止),也可以向进程发送其他信号。

   与kill()函数不同的是,raise()函数允许进程向自身发送信号。

函数格式

   下表分别列出了kill()和raise()的格式

      

      

 

基础实验

   本实验首先使用 fork()创建了一个子进程,接着为了保证子进程不在父进程调用kill()之前退出,在子进程中使用raise()函数向自身发送 SIGSTOP信号,使子进程暂停。接下来在父进程中调用kill()向子进程发送信号,在该实验中使用的是SIGKILL。实验代码如下:

   kill_raise.c文件点此下载

      

   编译后执行的效果如下图

   

   你瞧瞧,多狠啊,都不让子进程输出第22行的话,直接啪的就给人拍那里了。

   另外,建议你去掉27行的代码再执行一遍试一试看看有什么不同。

信号捕捉函数: alarm()、pause()

函数说明

    alarm()也称为闹钟函数,它可以在进程中设置一个定时器,当定时器指定的时间到时,它就向进程发送SIGALARM信号。要注意的是,一个进程只能有一个闹钟时间,如果在调用alarm()之前已设置过闹钟时间,则任何以前的闹钟时间都被新值所代替。

   pause()函数用于将调用进程挂起直至捕捉到信号为止。这个函数很常用,通常可以用于判断信号是否已到。

函数格式

   

    

 

 

基础实验

    本实验实际上是完成了一个简单的sleep()函数的功能,程序如下图

     

   编译执行后,结果如下图

   

  可以看到12行的语句根本就没执行,其实想想程序的执行流程就很清除,首先程序定时,执行到11行pause();时进程会被挂起,当计时到,发出信号SIGALARM,这时pause()捕捉到信号,进程直接被终止。

    现在屏蔽掉11行,如下

    

   再次编译执行,结果如下图

   

  下一节学习一下信号的处理,如需转载,请注明出处:http://blog.youkuaiyun.com/mybelief321/article/details/9078193

  最后,顺祝大家端午节快乐!!也顺祝今年的金九银十顺利!

<think>我们正在讨论进程间通信中的信号类型。根据提供的引用,信号异步通信机制,用于传递简单的事件通知。现在需要回答用户的问题:进程间通信使用的信号类型有哪些? 注意:在Unix/Linux系统中,信号有标准信号和实时信号之分。标准信号有预定义的编号和名称,而实时信号是后来添加的,用于实时应用。 根据POSIX标准,常见的标准信号及其用途如下: 1. SIGHUP (1):终端挂起或控制进程终止。 2. SIGINT (2):键盘中断(Ctrl+C)。 3. SIGQUIT (3):键盘退出(Ctrl+\),产生核心转储。 4. SIGILL (4):非法指令。 5. SIGTRAP (5):跟踪/断点陷阱。 6. SIGABRT (6):调用abort函数时产生。 7. SIGBUS (7):总线错误(错误的内存访问)。 8. SIGFPE (8):算术运算异常(如除以零)。 9. SIGKILL (9):立即终止进程(不可捕获或忽略)。 10. SIGUSR1 (10):用户自定义信号1。 11. SIGSEGV (11):无效内存引用(段错误)。 12. SIGUSR2 (12):用户自定义信号2。 13. SIGPIPE (13):管道破裂:写一个没有读端口的管道。 14. SIGALRM (14):由alarm函数设置的定时器超时。 15. SIGTERM (15):终止信号(可被捕获,是kill命令的默认信号)。 16. SIGSTKFLT (16):协处理器栈错误(较少使用)。 17. SIGCHLD (17):子进程状态改变(终止或停止)时发送给父进程。 18. SIGCONT (18):继续执行已停止的进程。 19. SIGSTOP (19):停止进程的执行(不可捕获或忽略)。 20. SIGTSTP (20):终端停止信号(Ctrl+Z)。 21. SIGTTIN (21):后台进程尝试从终端读取。 22. SIGTTOU (22):后台进程尝试向终端写入。 23. SIGURG (23):紧急数据出现在套接字上。 24. SIGXCPU (24):超过CPU时间限制。 25. SIGXFSZ (25):文件大小超出限制。 26. SIGVTALRM (26):虚拟定时器超时。 27. SIGPROF (27):性能分析定时器超时。 28. SIGWINCH (28):窗口大小改变。 29. SIGIO (29):文件描述符上可进行I/O操作(异步I/O)。 30. SIGPWR (30):电源故障(系统特有)。 此外,还有实时信号(从SIGRTMIN到SIGRTMAX),这些信号没有预定义的含义,由应用程序自定义使用。 在引用[1]中提到,信号异步通信机制,用于通知进程发生了某个事件。引用[2]也提到信号是在软件层次上对中断机制的一种模拟,并且信号可以直接进行用户空间进程和内核进程之间的交互。 因此,在回答中,我们需要列出常见的标准信号,并说明实时信号的存在。 注意:不同的系统可能支持不同的信号,但上述信号在大多数Unix/Linux系统中是通用的。 根据要求,我们需要在回答中自然地添加引用标识。由于引用[1]和[2]都提到了信号的基本概念,我们可以将引用标识放在介绍信号概念的部分。 另外,用户之前的问题是关于孤儿进程、僵尸进程和守护进程,而本次问题转向了进程间通信信号,所以我们在回答中不需要涉及之前的内容,除非有直接关联(例如,SIGCHLD信号与子进程终止相关,这在处理僵尸进程时非常重要)。 因此,我们可以这样组织回答: 1. 介绍信号进程间通信中的作用(引用[1]和[2])。 2. 列出常见的标准信号(重点列出一些常用的,不需要全部,但可以给出一个表格,或者分类列出)。 3. 简要说明实时信号。 4. 最后,可以提及一些与信号处理相关的函数(如kill, raise, signal, sigaction等)作为补充,因为用户可能也会关心如何使用这些信号。 但是,用户的问题明确是“信号类型有哪些”,所以重点在类型(即信号名称和含义)。 由于信号种类较多,我们可以分类列出(如终止信号、停止/继续信号、定时器信号、用户自定义信号等)。 同时,根据要求,我们需要生成相关问题。 注意:在回答中,如果提到某个信号的具体行为,可以引用[2]中关于信号处理方式的内容(如阻塞、忽略等)。 但是,引用[3]中给出了一个使用killpause的例子,我们可以作为示例代码。 不过,用户的问题并没有要求示例代码,所以我们可以选择是否提供。如果提供,可以放在最后作为补充。 因此,回答结构如下: ### 进程间通信信号类型 信号进程间通信异步通信机制,用于通知进程发生了特定事件[^1][^2]。在Unix/Linux系统中,信号分为**标准信号**(1-31)和**实时信号**(SIGRTMIN-SIGRTMAX)两类。 #### 一、标准信号(常用) 以下是常见的标准信号及其用途: | 信号名称 | 编号 | 默认行为 | 触发条件 | |----------|------|----------|---------| | SIGHUP | 1 | 终止 | 终端挂断或控制进程终止 | | SIGINT | 2 | 终止 | 键盘中断(Ctrl+C) | | SIGQUIT | 3 | 终止并转储核心 | 键盘退出(Ctrl+\) | | SIGABRT | 6 | 终止并转储核心 | 调用abort()函数 | | SIGKILL | 9 | 终止 | 强制立即终止进程(不可捕获或忽略) | | SIGALRM | 14 | 终止 | 定时器超时(由alarm/setitimer设置) | | SIGTERM | 15 | 终止 | 终止进程(可被捕获,kill命令默认) | | SIGSTOP | 19 | 停止进程 | 停止进程执行(不可捕获或忽略) | | SIGCONT | 18 | 继续执行 | 让停止的进程继续执行 | | SIGCHLD | 17 | 忽略 | 子进程状态改变(终止或停止) | | SIGUSR1 | 10 | 终止 | 用户自定义信号1 | | SIGUSR2 | 12 | 终止 | 用户自定义信号2 | > 注:完整标准信号列表可通过`kill -l`命令查看。 #### 二、实时信号 - 编号范围:`SIGRTMIN`(通常为34)到`SIGRTMAX`(通常为64) - 特点:无预定义含义,由应用程序自定义使用,支持排队(不会丢失) #### 三、信号处理方式 进程对信号的处理方式包括: 1. **默认行为**:系统预定义(终止、忽略、停止、继续等) 2. **忽略信号**:`SIG_IGN` 3. **自定义处理**:注册信号处理函数捕获信号 4. **阻塞信号**:延迟信号传递(信号被加入待处理信号集) > 注意:`SIGKILL`和`SIGSTOP`不能被捕获、忽略或阻塞[^2]。 #### 示例:发送信号 引用[3]展示了发送信号的代码: ```c #include <sys/types.h> #include <signal.h> #include <stdio.h> #include <unistd.h> int main() { // 给当前进程发送SIGKILL kill(getpid(), SIGKILL); // 或使用raise(SIGKILL); pause(); // 挂起进程,等待信号 return 0; } ``` #### 关键点 - 信号异步事件通知机制,适用于轻量级通信[^1]。 - 内核通过更新目标进程的待处理信号集来传递信号[^2]。 --- ### 相关问题 1. 如何捕获并处理SIGCHLD信号来避免僵尸进程? 2. 实时信号与标准信号的主要区别是什么? 3. 在C语言中如何注册自定义信号处理函数? 4. 为什么SIGKILL和SIGSTOP不能被捕获? 引用: [^1]: 进程间通信信号)的异步通信机制 [^2]: Linux进程间通信信号的处理与传递 [^3]: 通过killraise发送信号的示例 注意:在表格中,我们只列出了一些常用信号,实际标准信号有30多个,但用户通常关注这些。</think>### 进程间通信信号类型详解 在进程间通信(IPC)中,信号是一种**异步通信机制**,用于在进程间传递简单的事件通知。以下是主要的信号类型及其功能: --- #### **一、标准信号(Regular Signals)** Linux系统定义了31个标准信号(编号1-31),核心类型包括: | 信号名称 | 编号 | 默认行为 | 主要用途 | |----------|------|----------------|----------------------------| | `SIGHUP` | 1 | 终止进程 | 终端连接断开时通知守护进程[^1] | | `SIGINT` | 2 | 终止进程 | 键盘中断(Ctrl+C) | | `SIGQUIT`| 3 | 终止+核心转储 | 键盘退出(Ctrl+\) | | `SIGKILL`| 9 | **强制终止** | 立即杀死进程(不可捕获)[^3] | | `SIGTERM`| 15 | 终止进程 | 优雅终止(kill默认信号) | | `SIGCHLD`| 17 | 忽略 | 子进程状态改变通知父进程[^1] | | `SIGCONT`| 18 | 继续执行 | 恢复被暂停的进程 | | `SIGSTOP`| 19 | **暂停进程** | 暂停进程(不可捕获) | | `SIGTSTP`| 20 | 暂停进程 | 终端暂停(Ctrl+Z) | | `SIGALRM`| 14 | 终止进程 | 定时器超时(alarm())[^3] | > 通过 `kill -l` 命令可查看完整信号列表。 --- #### **二、实时信号(Real-time Signals)** - **编号范围**:`SIGRTMIN`(通常34)到 `SIGRTMAX`(通常64) - **关键特性**: - 支持信号排队(避免丢失) - 携带附加数据(通过`sigqueue()`) - 按先进先出顺序传递 - **典型用途**:高可靠性应用(如实时系统) --- #### **三、信号处理方式** 进程对信号的处理方式包括: 1. **默认行为**(终止/忽略/暂停/继续) 2. **忽略信号**:`signal(SIGINT, SIG_IGN)` 3. **自定义处理**:注册信号处理函数 ```c void handler(int sig) { printf("Received signal: %d\n", sig); } signal(SIGUSR1, handler); // 捕获用户自定义信号 ``` 4. **阻塞信号**:延迟传递(通过`sigprocmask()`) > 特殊规则:`SIGKILL`和`SIGSTOP`**不可被捕获、忽略或阻塞**[^2]。 --- #### **、关键特性总结** 1. **异步传递**:信号可能在任何时间点中断进程[^1] 2. **轻量级**:仅传递事件ID,不携带大量数据[^1] 3. **内核中转**:内核负责信号传递和管理[^2] 4. **跨权限通信**:用户进程与内核间可通过信号交互[^2] --- ### **相关问题** 1. 如何通过`sigaction()`实现可靠信号处理? 2. 实时信号与标准信号在排队机制上有何区别? 3. 为什么`SIGCHLD`信号对避免僵尸进程至关重要? 4. 在多线程程序中信号处理有哪些特殊规则? > 引用: > [^1]: 进程间通信信号)的异步通信机制 > [^2]: Linux进程间通信信号的处理与传递 > [^3]: 通过killraise发送信号的示例
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

玖零大壮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值