|
@@ -1,3 +1,142 @@
|
|
|
-# 任务管理
|
|
|
+### Eonix内核的任务管理
|
|
|
|
|
|
+Eonix内核的任务管理系统通过线程、进程、进程组、会话和信号机制,构建了一个高效、灵活的多任务管理框架。以下是对其任务管理部分的全面介绍:
|
|
|
|
|
|
+---
|
|
|
+
|
|
|
+### 1. 核心设计概述
|
|
|
+任务管理是内核调度和进程间通信的基础,其核心组件包括:
|
|
|
+- 线程(`Thread`): 是调度的基本单位。
|
|
|
+- 进程(`Process`): 是资源分配的基本单位,包含线程的集合。
|
|
|
+- 进程组(`ProcessGroup`): 组织和管理一组相关进程,通常用于信号广播。
|
|
|
+- 会话(`Session`): 包含多个进程组,为作业控制和终端管理提供支持。
|
|
|
+- 信号机制: 负责进程间通信、异常处理和任务状态控制。
|
|
|
+
|
|
|
+Eonix的任务管理通过统一的接口和模块化设计,支持复杂的任务调度、资源管理和进程间交互。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 2. 线程管理
|
|
|
+
|
|
|
+线程是Eonix内核调度的基本单位,由`Thread`结构体表示,每个线程包含独立的内核栈(`KernelStack`)、文件系统上下文和文件描述符表等资源。线程的状态管理(如`Running`、`ISleep`、`USleep`等)通过调度器接口完成,支持线程在用户态和内核态之间高效切换。线程中有进程的指针,这样可以做到多个线程共享一部分资源。通过`InterruptContext`和`TaskContext`实现上下文保存与切换,确保任务运行的连续性和调度的高效性。
|
|
|
+
|
|
|
+每个线程由`Thread`结构体表示,包含:
|
|
|
+- TID(`tid`): 唯一标识。
|
|
|
+- 线程状态(`state`): 包括`Preparing`、`Running`、`Ready`、`Zombie`等多种状态,用于调度器管理。
|
|
|
+- 内核栈(`kstack`): 为每个线程分配一个独立的内核栈,用于上下文切换和异常处理。
|
|
|
+- 文件系统上下文(`fs_context`)和文件描述符表(`files`): 提供线程的独立资源管理。
|
|
|
+
|
|
|
+#### 线程的生命周期
|
|
|
+
|
|
|
+线程的创建方面,初始线程通过`Thread::new_for_init`创建。像在`clone`或`exec`等中复制的线程通过`Thread::new_cloned`创建,和父线程一起共享一个进程的资源。状态管理通过调度器(`Scheduler`)接口完成,支持从`Running`切换到`ISleep`或`USleep`等状态。 上下文切换使用`InterruptContext`和`TaskContext`保存线程的寄存器状态,支持线程在内核和用户态间切换。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 3. 进程管理
|
|
|
+
|
|
|
+进程是资源分配的基本单位,由`Process`结构体表示。每个进程具有唯一的PID,并包含线程集合、父子关系、内存管理信息(`MMList`)以及所属的进程组和会话。进程的创建通过克隆现有进程实现,支持资源继承,同时初始进程(如`init`进程或闲置进程)通过专门方法生成。进程支持多线程资源共享,通过`WaitList`等待子进程状态变化(如退出或收到信号),并结合信号机制实现进程间通信和同步操作。进程的多线程安全性由锁机制保障。
|
|
|
+
|
|
|
+#### 进程的基本结构
|
|
|
+每个进程由Process结构体表示,包含:
|
|
|
+
|
|
|
+- PID(`pid`): 每个进程都有一个唯一的标识符,用于区分其他进程。
|
|
|
+- 线程集合(`threads`): 用`BTreeMap`储存一个包含属于该进程的所有线程的列表。
|
|
|
+- 子进程(`children`): 使用`BTreeMap`存储该进程的所有子进程,支持高效查找和管理。
|
|
|
+- 内存管理信息(`mm_list`): 使用`MMList`表示进程的内存映射,管理用户态和内核态的地址空间。
|
|
|
+- 父进程(`parent`): 引用父进程,支持动态更新和安全访问。
|
|
|
+- 所属进程组(`pgroup`): 每个进程都属于一个进程组,用于协作管理和信号广播。
|
|
|
+- 会话(`session`): 进程所属的会话,支持终端绑定和作业控制。
|
|
|
+
|
|
|
+#### 进程的生命周期
|
|
|
+
|
|
|
+进程创建通过`Process::new_cloned`方法实现新进程的创建,子进程会继承父进程的大部分资源(如内存和会话)。对于系统初始化的特殊进程(如init进程),通过`Process::new_for_init`创建。
|
|
|
+
|
|
|
+进程终止时,调用`ProcessList::do_kill_process`方法将进程标记为`Zombie`状态,并清理相关资源,包括用户态内存、子进程管理以及从进程组和会话中移除。如果终止的是会话领导进程,关联的控制终端也会被释放。同时,其没有退出的所有子进程都会被收容到init进程中,确保每个进程都可以正常地被回收。
|
|
|
+
|
|
|
+#### 进程管理与多线程支持
|
|
|
+
|
|
|
+`ProcessList`是管理所有进程的核心结构,通过全局实例`GLOBAL_PROC_LIST`维护。`ProcessList`使用`BTreeMap`存储所有的进程、线程、进程组和会话,并通过`RwSemaphore`实现线程安全访问。关键操作包括:
|
|
|
+1. 添加与移除: 通过`add_process`和`remove_process`方法实现进程的动态添加与移除。在移除进程时,还会同步清理其线程、会话和进程组信息。
|
|
|
+2. 查询: 提供`try_find_process`、`try_find_pgroup`等方法,支持高效查找进程和相关结构。
|
|
|
+调度整合: 结合调度器`Scheduler`,支持线程和进程的动态调度,确保高效的多任务管理。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 4. 信号管理
|
|
|
+
|
|
|
+信号是Eonix内核进程间通信和异常处理的核心机制,用于实现进程控制、任务协作和异常处理。信号通过`Signal`结构体表示,并结合`SignalList`和`SignalAction`实现挂起、屏蔽和处理机制。信号的设计符合POSIX标准,支持多种信号类型(如`SIGKILL`、`SIGSTOP`等),并通过进程组和会话实现信号广播和作业控制。
|
|
|
+
|
|
|
+#### 信号的基本结构
|
|
|
+
|
|
|
+信号由`Signal`结构体表示,包含信号类型,即每个信号通过唯一的数字标识,支持常见的POSIX信号类型,包括:
|
|
|
+- 终止信号: 如`SIGTERM`、`SIGKILL`,用于立即终止进程。
|
|
|
+- 停止信号: 如`SIGSTOP`、`SIGTSTP`,用于暂停进程。
|
|
|
+- 用户自定义信号: 如`SIGUSR1`、`SIGUSR2`,用于用户进程间通信。
|
|
|
+- 忽略信号: 如`SIGCHLD`,默认行为是被内核忽略。
|
|
|
+- 核心转储信号: 如`SIGSEGV`、`SIGFPE`,会生成核心转储文件并终止进程。
|
|
|
+
|
|
|
+#### 信号管理与挂起
|
|
|
+
|
|
|
+信号管理由`SignalList`完成,负责信号的挂起、屏蔽和优先级管理。挂起信号存储在`BinaryHeap`中,按照优先级排序,以确保高优先级信号优先处理。通过`SignalList::mask`和`SignalList::unmask`动态管理信号掩码,决定哪些信号会被屏蔽。对于线程或进程接收到的信号,会首先判断其屏蔽状态,屏蔽信号会进入挂起队列,等待后续处理。
|
|
|
+
|
|
|
+#### 信号处理与分发
|
|
|
+
|
|
|
+信号的处理方式由`SignalAction`定义,支持以下三种模式:
|
|
|
+- 默认行为: 系统为每种信号定义的默认处理方式,如终止进程、暂停进程或忽略信号。
|
|
|
+- 自定义Handler: 用户可以为特定信号设置自定义处理器,在用户态执行信号处理逻辑。
|
|
|
+- 忽略信号: 指定某些信号被忽略,如`SIGCHLD`默认不会影响进程运行。
|
|
|
+
|
|
|
+信号分发可以针对单个线程、进程组或会话的前台进程组进行广播。通过`SignalList::raise`方法,信号被加入目标对象的挂起信号队列,并根据优先级等待处理。
|
|
|
+
|
|
|
+#### 信号与上下文切换
|
|
|
+
|
|
|
+信号处理与上下文切换紧密结合。当线程被调度器切换到运行状态时,内核会检测其挂起信号列表,并调用相应的信号处理器。信号处理器通过`SignalAction::handle`加载到用户堆栈中,修改`InterruptContext`返回地址,将执行跳转到用户态的信号处理函数中。
|
|
|
+
|
|
|
+对于不可屏蔽信号(如`SIGKILL`、`SIGSTOP`),内核会立即终止或暂停目标进程,不会经过挂起队列或信号处理器。
|
|
|
+
|
|
|
+#### 信号的进程间通信
|
|
|
+
|
|
|
+信号是进程间通信的重要机制,支持通过进程组和会话范围实现信号广播。例如:
|
|
|
+- 通过`ProcessGroup::raise`将信号发送给整个进程组。
|
|
|
+- 使用`Session::raise_foreground`向会话的前台进程组发送信号,实现作业控制。
|
|
|
+
|
|
|
+信号分发结合进程组和会话机制,为任务管理中的状态同步和协作提供了基础设施。
|
|
|
+
|
|
|
+Eonix内核的信号管理模块通过模块化设计和POSIX标准兼容,实现了灵活的进程间通信和异常处理。挂起信号、屏蔽机制和优先级队列确保信号的高效处理,自定义处理器扩展了信号的适用场景。信号与上下文切换和调度器紧密结合,为系统的异常响应和作业控制提供了强大支持,同时通过进程组和会话的广播功能增强了信号的可扩展性。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 5. 会话、进程组与作业控制
|
|
|
+
|
|
|
+Eonix内核中的会话和进程组机制是任务管理系统的重要组成部分,为进程的组织管理、信号广播和作业控制提供了基础。会话通过将多个进程组归为一个集合,结合控制终端(`Terminal`)实现用户与作业的交互。作业控制支持前台/后台作业切换、暂停与恢复等操作,使内核能够高效管理任务协作。
|
|
|
+
|
|
|
+#### 会话的基本结构
|
|
|
+
|
|
|
+会话由`Session`结构体表示,通过`SessionJobControl`管理前台进程组和控制终端,使用读写信号量(`RwSemaphore`)确保多线程安全访问。包含以下核心组件:
|
|
|
+
|
|
|
+- SID(`sid`): 由会话领导进程的PID决定,是会话的唯一标识。
|
|
|
+- 领导进程(`leader`): 会话的创建者,负责初始化会话并管理其生命周期。
|
|
|
+- 前台进程组(`foreground`): 当前与用户交互的进程组,用户输入和信号优先发送到此进程组。
|
|
|
+- 控制终端(`control_terminal`): 绑定到会话的终端设备,用于用户与前台进程组的交互。
|
|
|
+- 进程组集合(`groups`): 存储会话中的所有进程组,支持动态添加和移除。
|
|
|
+
|
|
|
+#### 进程组的基本结构
|
|
|
+
|
|
|
+进程组由`ProcessGroup`结构体表示,是进程的集合,主要用于信号广播和作业管理。支持成员的动态添加和移除,并通过所属会话与控制终端关联。。每个进程组包含以下部分:
|
|
|
+
|
|
|
+- 进程组ID(`pgid`): 用于唯一标识进程组,通常等于其领导进程的PID。
|
|
|
+- 领导进程(`leader`): 进程组的创建者,负责管理该组的资源和信号。
|
|
|
+- 所属会话(`session`): 进程组所属的会话,确保跨进程组的协作一致性。
|
|
|
+- 成员进程(`processes`): 使用`BTreeMap`存储进程组内的所有进程,支持快速查找和广播信号。
|
|
|
+
|
|
|
+#### 作业控制
|
|
|
+
|
|
|
+作业控制是通过会话的前台进程组和控制终端实现的,支持以下功能:
|
|
|
+
|
|
|
+1. 前后台作业切换: 通过`Session::set_foreground_pgid`设置前台进程组,使用户输入和信号优先发送到新的作业。
|
|
|
+2. 信号广播: 通过`Session::raise_foreground`将信号发送给前台进程组,常用于暂停(`SIGSTOP`)或恢复(`SIGCONT`)前台作业。
|
|
|
+3. 终端绑定: 使用`Session::set_control_terminal`将终端绑定到会话,确保用户输入输出只影响绑定的会话。会话领导进程拥有设置和释放控制终端的权限。
|
|
|
+
|
|
|
+会话与进程组的管理由`ProcessList`模块实现,新会话通过`Session::new`创建,进程组通过`Session::new_group`添加到会话。移除进程组时,如果会话中无其他进程组,会自动解除与控制终端的绑定。`ProcessList`提供方法查找会话和进程组,如`try_find_session`和`try_find_pgroup`。信号通过`ProcessGroup::raise`广播到整个进程组,或通过`Session::raise_foreground`广播到前台进程组。
|
|
|
+
|
|
|
+会话和进程组与信号机制紧密协作,提供多层次的任务控制能力。会话通过前台进程组分发信号,实现广播,可以控制用户当前交互作业。用户可以通过绑定的终端发送信号(如`SIGSTOP`或`SIGCONT`)控制作业状态切换。当会话领导进程终止时,内核会自动释放绑定的控制终端,并将会话中所有进程移至后台。
|