diff --git a/docs/index.rst b/docs/index.rst index 238cb7ed..1c0e7ea8 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -22,6 +22,7 @@ kernel/locking/index kernel/process_management/index kernel/sched/index + kernel/ipc/index kernel/memory_management/index kernel/filesystem/index kernel/debug/index diff --git a/docs/kernel/ipc/index.rst b/docs/kernel/ipc/index.rst new file mode 100644 index 00000000..c830c878 --- /dev/null +++ b/docs/kernel/ipc/index.rst @@ -0,0 +1,10 @@ +==================================== +进程间通信 +==================================== + + 这里是DragonOS进程间通信(IPC)的说明文档。 + +.. toctree:: + :maxdepth: 1 + + signal diff --git a/docs/kernel/ipc/signal.md b/docs/kernel/ipc/signal.md new file mode 100644 index 00000000..9ad2d9f5 --- /dev/null +++ b/docs/kernel/ipc/signal.md @@ -0,0 +1,82 @@ +# Signal信号 + +:::{note} +本文Maintainer: 龙进 + +Email: +::: + +  信号是一种进程间通信机制,当我们发送一个信号给特定的进程,就能触发它的特定行为(例如退出程序,或者运行一些信号处理程序)。信号是发送到进程或同一进程内的特定线程的异步通知,用于通知它有事件发生。信号的常见用途是中断、挂起、终止或终止进程。发送信号时,操作系统会中断目标进程的正常执行流程以传递信号。可以在任何非原子指令期间中断执行。如果该进程之前注册了一个信号处理程序,则执行该例程。否则,将执行默认信号处理程序。 + +  信号类似于中断,区别在于中断由CPU调解并由内核处理,而信号在内核中产生(也可通过系统调用让内核产生)并由各个进程或内核的默认处理函数处理。 + +## 1.信号处理概要 + +### 1.1 信号发送 + +  当进程A想发送信号给进程B的时候,使用`kill(pid, signal)`接口进行发送。然后陷入内核的`sys_kill()`函数中进行处理。然后内核将会把信号加入目标进程的pcb的`sigpending`中。 + +示意图如下: + +```text + ┌────────────┐ + │ Process A: │ + │ │ + │ sys_kill │ + └──────┬─────┘ + │ + │ + ┌──────▼──────┐ ┌────────────────────┐ + │ Send Signal ├────►Add to sigpending of│ + └─────────────┘ │ process B. │ + └────────────────────┘ + +``` + +### 1.2 信号处理 + +  进程会在退出内核态的时候,跳转到`do_signal()`函数内,检查当前是否有需要被处理的信号,如果有的话,就会开启信号处理流程。 + +信号处理流程示意图: + +```text + + ┌───────────────────────┐ + │ Process B: │ + │ ◄─────────────────────────────────┐ + │ Return from syscall...│ │ + └─────────┬─────────────┘ │ + │ │ + │ │ + │ ┌────────────────┐ │ + ┌─────▼─────┐ default │ │ │ + │ do_signal ├────────► │ stop process B.│ │ + └─────┬─────┘ action │ │ │ + │ └────────────────┘ │ + │ custom action │ + ┌──────▼───────┐ │ + │ setup signal │ │ + │ frame │ │ + └──────┬───────┘ │ + │jump to │ + ┌──────▼───────┐ ┌────────────┐ sys_sigreturn ┌────────┴────────┐ + │ userland ├─►sa_restorer ├──────────────►│Restore the stack│ + │ sig handler │ └────────────┘ │ frame. │ + └──────────────┘ └─────────────────┘ + +``` + +- 如果内核检查发现,进程没有指定信号处理函数,且信号处理动作不是“忽略”,那就会杀掉进程。 +- 如果内核发现该信号没有被忽略,那么将会: + - 备份当前内核栈 + - 设置信号处理的用户态栈帧 + - 回到用户态,执行信号处理函数 + - 信号处理函数结束之后,将会进入由libc提供的__sa_restorer中,发起`sys_sigreturn()`系统调用,回到内核态 + - 内核恢复处理信号之前的内核栈。 + - 信号处理流程结束,内核继续执行“返回用户态”的过程。 +- 如果内核发现当前信号被忽略,那么就检查下一个信号。 +- 发现没有任何需要处理的信号时,返回用户态。 + +## 2. 其他问题 + +  暂无。