【进程通信】信号的捕捉原理&&用户态与内核态的区别

简介: 【进程通信】信号的捕捉原理&&用户态与内核态的区别

1.前言

在之前的学习中,我们已经知道了信号是如何产生的,也知道了进程是如何记录一个信号的。如果进程收到了一个信号且没有屏蔽这个信号,则会将信号编号作为handler数组的下标执行该信号的处理函数。我们将处理特定信号的事件的过程叫做信号的捕捉。下面将带大家了解从操作系统的角度看是如何捕捉信号的。

2.了解内核态和用户态的区别

用户态和内核态是操作系统中两种不同的执行模式,对应着两种执行权限。处于内核态的执行模式下的执行权限比用户态的高。 遇到需要较高权限的代码,就进入内核态去执行。这两种模式对系统的安全和稳定性起到了至关重要的作用。下面来具体说说这两种状态。

  • 用户态:像上面说的,用户态其实具有的权限是有限的,用户态下的程序不能直接访问硬件资源或者进行某些敏感的操作 ,如系统调用等。
  • 内核态:内核态就是操作系统内核运行的模式,具有最高权限。内核态下的代码可以访问任何CPU指令并访问任何内存地址。内核态主要用于操作系统内核和设备驱动程序的运行。

2.1虚拟内存视角

从虚拟内存的角度上来看,内核态和用户态的区别体现在内存空间的分配和访问权限上。

我们知道,所有的进程都有一个统一的虚拟地址空间,以32为操作系统为例,3-4G的地址空间是内核空间(高地址),0-3G的地址空间是用户空间(低地址)。最重要的是,内核空间和用户空间都有各自的页表(内核级页表和用户级页表)。这也就意味着每一个进程的空间内,包含了操作系统本身这个程序的空间。

类似于共享空间,即使每一个进程空间都有内核空间,但所有进程的内核空间其实是共享的,这就说明了,内核级页表在任何进程中都是一样的,映射的都是同一个内核空间。这也解释了,为什么无论进程如何切换,我们都能找到操作系统。因为不同进程的3-4G的地址空间是同一个操作系统。

用户态和内核态访问进程空间的区别:

  • 处于用户态的程序只能访问用户空间的内存地址,而无法访问内核空间的地址。
  • 内核态可以访问整个虚拟空间地址,包括用户空间和内核空间。

2.2内核态和用户态的区别总结

  1. 权限不同:用户态权限有限,户态权限最高
  2. 安全性:由于权限较低,用户态不能访问系统核心,较为安全。而内核态具有完全控制权,一旦出错可能导致整个系统崩溃。
  3. 系统调用:用户态不能执行系统调用,需要切换到内核态。
  4. 切换条件:用户态切换到内核态通常是发生中断或者是异常,是需要条件的。而内核态可以随时切换为用户态。

共同点:内核态和用户态之间的切换都涉及到上下文的切换,都会增加额外的开销

到此,我们就大概了解了什么是用户态与内核态,也知道了这两者之间的区别。但是这和信号的捕捉有什么关系呢?

处理信号会涉及到内核态和用户态之间的转换吗?答案是会的。无论是发生中断还是异常,都会伴随信号的产生以及捕捉 。当信号到达一个进程的时候,操作系统会进行一些必要的操作来处理这个信号。这个过程就涉及到内核态和用户态之间的切换。

3.内核如何实现信号的捕捉

如果信号的的处理动作是用户自定义的,在信号递达时就调用这个函数,这就称为捕捉信号。但是由于信号的处理函数是在用户空间的,处理的过程就势必会伴随用户态内核态之间的切换。假设用户程序自定义了SIGQUIT信号的处理函数sighandler。程序捕捉该信号是的状态变化过程如下:

  1. 开始运行程序,程序处于用户态
  2. 运行时进程收到信号SIGQUIT,发生中断。CPU保存上下文,并把当前进程切换为内核态,以便处理信号的相关操作。
  3. 由于信号的处理动作是自定义的,切换回用户态执行sighandler函数。
  4. 信号处理函数执行完,通常会执行特殊的系统调用sigreturn(该函数回到上次被中断的地方),此时又要切换回内核态。假如自定义信号处理函数调用了exit,则终止进程。
  5. 执行sigreturn,切换回用户态,回到上次中断发生的地方并向下继续执行代码。

至此,中断信号的产生到处理,一共经历了四次状态的切换。(假设中间没有终止进程)

为了更好理解,可以观察下图:

4.sigaction函数

sigaction和signal都是用来处理信号的函数,但是sigaciton是一种更为强大和灵活的喜好处理机制,提供了更多的选项和更高的可靠性。

函数原型如下:

#include <signal.h>
int sigaction(int signo, const struct sigaction *act, struct sigaction *oact);
  • signo表示要捕捉的信号
  • act是指向sigaction结构体的指针,用于指定信号新的处理行为。为NULL使用系统默认的信号处理函数。
  • lodact也是指向sigaction结构体的指针,用于保存旧的信号处理行为。为NULL表示不保存。
  • 调用成功返回0,否则-1.

4.1sigactoin结构体

sigaction结构体定义如下:

struct sigaction {
    void (*sa_handler)(int);          // 信号处理函数
    void (*sa_sigaction)(int, siginfo_t *, void *); // 用于处理附加信息的信号处理函数
    sigset_t sa_mask;                 // 在处理信号时阻塞的信号集
    int sa_flags;                     // 行为标志
    void (*sa_restorer)(void);        // 不常用,可以忽略
};

sigaction结构体中不仅包含了信号的处理函数,还包含了很多其它的选项,例如可以在处理信号的时候阻塞其它信号(sa_mask),以防止竞争条件。

4.2扩展

当某个信号的处理函数正在执行时,内核将自动将当前信号加入进程信号的阻塞集合中。当信号处理完之后又会将该信号从阻塞信号集中移除。 这种机制保证了在处理信号的时候不会重复处理同种信号。也可以通过设置sa_mask的值来屏蔽其它信号。


相关文章
进程空间管理:用户态和内核态
【9月更文挑战第21天】用户态虚拟空间包括代码、全局变量、堆、栈及内存映射区等。`struct mm_struct` 定义了这些区域的统计信息和位置,如 `total_vm` 表示总映射页数,`locked_vm` 和 `pinned_vm` 分别表示锁定和不可移动的页数,`data_vm`、`exec_vm` 和 `stack_vm` 表示数据、可执行代码和栈的页数。此外,`mmap_base` 表示内存映射的起始地址。这些信息描述了用户态区域的布局和位置。
|
1月前
|
存储 Unix Linux
进程间通信方式-----管道通信
【10月更文挑战第29天】管道通信是一种重要的进程间通信机制,它为进程间的数据传输和同步提供了一种简单有效的方法。通过合理地使用管道通信,可以实现不同进程之间的协作,提高系统的整体性能和效率。
|
1月前
|
消息中间件 存储 供应链
进程间通信方式-----消息队列通信
【10月更文挑战第29天】消息队列通信是一种强大而灵活的进程间通信机制,它通过异步通信、解耦和缓冲等特性,为分布式系统和多进程应用提供了高效的通信方式。在实际应用中,需要根据具体的需求和场景,合理地选择和使用消息队列,以充分发挥其优势,同时注意其可能带来的复杂性和性能开销等问题。
|
2月前
|
存储 Python
Python中的多进程通信实践指南
Python中的多进程通信实践指南
27 0
|
3月前
|
Java Android开发 数据安全/隐私保护
Android中多进程通信有几种方式?需要注意哪些问题?
本文介绍了Android中的多进程通信(IPC),探讨了IPC的重要性及其实现方式,如Intent、Binder、AIDL等,并通过一个使用Binder机制的示例详细说明了其实现过程。
386 4
|
3月前
|
算法 调度 UED
操作系统中的进程管理:原理与实践
在数字世界的心脏跳动着无数进程,它们如同细胞一般构成了操作系统的生命体。本文将深入探讨进程管理的奥秘,从进程的诞生到成长,再到最终的消亡,揭示操作系统如何协调这些看似杂乱无章却又井然有序的活动。通过浅显易懂的语言和直观的比喻,我们将一起探索进程调度的策略、同步机制的重要性以及死锁问题的解决之道。准备好跟随我们的脚步,一起走进操作系统的微观世界,解锁进程管理的秘密吧!
73 6
|
3月前
|
Linux C语言
C语言 多进程编程(四)定时器信号和子进程退出信号
本文详细介绍了Linux系统中的定时器信号及其相关函数。首先,文章解释了`SIGALRM`信号的作用及应用场景,包括计时器、超时重试和定时任务等。接着介绍了`alarm()`函数,展示了如何设置定时器以及其局限性。随后探讨了`setitimer()`函数,比较了它与`alarm()`的不同之处,包括定时器类型、精度和支持的定时器数量等方面。最后,文章讲解了子进程退出时如何利用`SIGCHLD`信号,提供了示例代码展示如何处理子进程退出信号,避免僵尸进程问题。
|
3月前
|
NoSQL
gdb中获取进程收到的最近一个信号的信息
gdb中获取进程收到的最近一个信号的信息
|
4月前
|
消息中间件 存储 安全
python多进程并发编程之互斥锁与进程间的通信
python多进程并发编程之互斥锁与进程间的通信
|
4月前
|
消息中间件 资源调度 调度
进程与线程的区别
【8月更文挑战第24天】
42 0