linux內核進程管理(1)——創建,退出

linux源碼閱讀——進程管理(1)

  • 1. 進程的基本介紹
    • 1.1 linux中進程和線程的區別
    • 1.2 task_struct中的基本內容
    • 1.3 命名空間ns(namespace)
      • 命名空間結構圖
      • Linux 中的命名空間類型
    • 1.4 進程標識符
  • 2. 創建一個進程的流程
    • 2.1 CLONE宏
    • 2.2 創建進程系統調用
      • 1. do_fork流程——v6.9-kernel_clone
      • 2. do_fork中copy_process流程
        • (1). 標志沖突判斷
        • (2). dup_task_struct——分配task空間
        • (3). 檢查用戶的進程數量限制
        • (4). copy_creds復制或共享證書
        • (5). 檢查線程數量限制
        • (6). sched_fork——設置調度器相關參數
        • (7). copy_xxx——根據CLONE_FLAG復制或共享資源
      • 3. do_fork中的wake_up_new_task流程
  • 3. 進程的退出
    • 3.1 退出概念簡介
    • 3.2 exit_group線程組退出
      • 1. exit_group簡介
      • 2. exit_group具體流程
    • 3.3 kill

注 : 圖片來自《Linux內核深度解析 基于ARM64架構的Linux 4.x內核》(余華兵)

1. 進程的基本介紹

1.1 linux中進程和線程的區別

在課本教學中我們習慣將進程和線程看作兩種差別很大的東西,但是在實際的linux系統中,無論是進程還是線程都由所謂PCB(process control block) 也就是我們的 task_struct表示。

進程的虛擬地址空間分為用戶虛擬地址空間和內核虛擬地址空間,所有進程共享內核虛擬地址空間,每個進程有獨立的用戶虛擬地址空間

  • 先說結論
    • 進程——獨立擁有用戶虛擬地址空間
    • 用戶線程——共享用戶虛擬地址空間
    • 內核線程——沒有用戶虛擬地址空間

那么大家就要問了,什么是用戶虛擬地址空間(mm_struct),這個在講調度的時候介紹
術語約定

1.2 task_struct中的基本內容

成員說明
volatile long state;進程的狀態,使用volatile關鍵字,確保讀取都能得到最新的值
void *stack;指向內核棧, 進程在內核態下的運行“裝備”,確保進程在進入內核模式時能夠正確恢復上下文并安全執行內核代碼
pid_t pid;全局的進程號,同一PID命名空間下,pid唯一
pid_t tgid;全局的線程組標識符,在一個多線程進程中,多個線程會有不同的 pid,但它們的 tgid 會相同
struct pid_link pids[PIDTYPE_MAX];進程號,進程組標識符和會話標識符
struct task_struct __rcu *real_parent;real_parent指向真實的父進程, rcu(read-copy-update)并發編程機制
struct task_struct __rcu *parent;parent指向父進程:如果進程被另一個進程(通常是調試器)使用系統調用ptrace跟蹤,那么父進程是跟蹤進程,否則和real_parent相同
struct task_struct *group_leader;指向線程組的組長
const struct cred __rcu *real_cred;real_cred指向主體和真實客體證書,
const struct cred __rcu *cred;cred指向有效客體證書。通常情況下,cred和real_cred指向相同的證書,但是cred可以被臨時改變
char comm[TASK_COMM_LEN];進程名稱
int prio, static_prio, normal_prio;
unsigned int rt_priority;
unsigned int policy;
調度策略和優先級,dl,rt,cfs
cpumask_t cpus_allowed允許進程在哪些處理器上運行,處理器親和性
struct mm_struct *mm,*active_mm;指向內存描述符進程:mm和active_mm指向同一個內存描述符
內核線程:mm是空指針,當內核線程運行時,active_mm指向從進程借用的內存描述符
struct fs_struct *fs;文件系統信息,主要是進程的根目錄和當前工作目錄
struct files_struct *files;打開文件表
struct nsproxy *nsproxy;命名空間代理
struct signal_struct *signal;
struct sighand_struct *sighand;
sigset_t blocked, real_blocked;
sigset_t saved_sigmask;
struct sigpending pending;
信號處理,
signal_struct 用于存儲和管理進程的信號狀態。
sighand_struct 管理進程的信號處理程序。
blocked 和 real_blocked 控制進程哪些信號被阻塞,避免信號干擾進程執行。
saved_sigmask 保存和恢復進程的信號掩碼狀態。
sigpending 存儲待處理的信號。

1.3 命名空間ns(namespace)

和虛擬機相比,容器是一種輕量級的虛擬化技術,直接使用宿主機的內核,使用命名空間隔離資源。
命名空間
命名空間(Namespace)是 Linux 內核中的一種重要特性,它用于隔離不同進程的資源,使得多個進程能夠在同一臺機器上“仿佛”運行在獨立的系統中。命名空間技術是實現容器(如 Docker)的核心技術之一。命名空間通過提供資源的隔離,使得不同進程或容器能夠有自己獨立的資源視圖,如進程號(PID)、網絡、掛載等。

命名空間結構圖

命名空間結構

Linux 中的命名空間類型

Linux 支持多種類型的命名空間,每種命名空間用于隔離系統的某種資源。以下是 Linux 中常見的幾種命名空間類型:

  1. 進程號命名空間(PID Namespace)

    • 進程號命名空間使得每個進程可以擁有自己的進程號(PID)。在不同的進程號命名空間中,同一個 PID 號可以表示不同的進程。
    • 父進程的 PID 在子命名空間內不再是唯一的,而是局限于該命名空間中。比如,PID 1 代表的是該命名空間中的第一個進程,而不是宿主機上的第一個進程。
    • 這種隔離有助于容器化應用的管理,因為它們在容器內可以擁有從 1 開始的 PID,而與宿主機的進程號不沖突。
  2. 掛載命名空間(Mount Namespace)

    • 掛載命名空間允許不同的進程在不同的命名空間中看到不同的文件系統視圖。
    • 它能夠實現容器內進程看到的文件系統與宿主機或其他容器內進程看到的文件系統完全不同。例如,在容器中,你可以掛載不同的目錄,而這些掛載操作不會影響宿主機的文件系統。
    • 掛載命名空間是實現文件系統隔離的基礎
  3. 網絡命名空間(Network Namespace)

    • 網絡命名空間提供了進程之間網絡資源(如 IP 地址、路由表、網絡設備等)的隔離。
    • 每個網絡命名空間有自己的網絡接口、路由表、防火墻等配置。這樣,容器或進程在不同的網絡命名空間中,彼此之間不能直接通信,除非通過某種方式顯式地配置網絡連接。
    • 網絡命名空間使得容器能夠擁有自己的 IP 地址,甚至在不同的容器之間實現隔離的虛擬網絡。
  4. IPC 命名空間(IPC Namespace)

    • IPC 命名空間用于隔離進程間通信(IPC)機制,如信號量、消息隊列和共享內存。
    • 在不同的 IPC 命名空間中,進程看到的共享內存段、消息隊列等資源是隔離的。即使兩個進程有相同的 PID,它們也不能相互訪問對方的 IPC 資源。
  5. UTS 命名空間(UTS Namespace)

    • UTS 命名空間用于隔離主機名和域名系統(DNS)信息。
    • 在不同的 UTS 命名空間中,進程可以擁有獨立的主機名和域名,進而可以在容器中使用不同的主機名而不影響宿主機。
  6. 用戶命名空間(User Namespace)

    • 用戶命名空間用于隔離進程的用戶和組 ID(UID/GID)。
    • 在一個用戶命名空間內,進程可以有一個與宿主機完全不同的 UID 和 GID 映射。例如,容器中的進程可以運行在 UID 0(即 root 用戶),而在宿主機上可能對應的是一個普通用戶。這使得容器中的進程能夠具有 root 權限,但在宿主機上卻是以普通用戶身份運行,從而提高安全性。
  7. 時間命名空間(Time Namespace)(Linux 5.6 及以后版本)

    • 時間命名空間允許進程有自己獨立的時間視圖。每個時間命名空間可以有獨立的系統時間(即時間和時區設置)。這使得容器能夠有自己的時鐘和時間管理系統,而不依賴于宿主機的時間。
  8. cgroup 命名空間(Cgroup Namespace)(Linux 4.5 及以后版本)

    • cgroup 命名空間用于隔離進程的控制組(cgroup)信息。cgroup 是一種內核機制,用于對進程進行資源限制、優先級調度等管理。cgroup 命名空間允許每個進程組(如容器)有自己獨立的 cgroup 層次結構。

命名空間(Namespace)是 Linux 內核提供的一種資源隔離機制,它通過為進程提供獨立的資源視圖,確保不同進程或容器之間的隔離。命名空間的類型包括 PID、網絡、掛載、IPC、UTS、用戶等,這些命名空間在容器化技術、進程管理、安全性等方面起著關鍵作用。通過使用命名空間,Linux 能夠在同一臺機器上運行多個互相隔離的進程或容器,從而實現更高效和安全的資源管理。

1.4 進程標識符

  • 進程標識符 pid
  • 線程組標識符 tgid
  • 進程組標識符 pgid
  • 會話標識符 sid
    sid是多個兄弟在一起(shell),pgid是爸爸帶一堆兒子(fork)

會話和進程組被設計用來支持 shell 作業控制,shell 為執行單一命令或者管道的進程創建一個進程組

2. 創建一個進程的流程

2.1 CLONE宏

想要了解進程的創建流程首先需要了解,clone都具備哪些標識

標志類別作用
CSIGNAL信號相關標志子進程退出時發送給父進程的信號掩碼。
CLONE_VM資源共享標志父子進程共享虛擬內存空間,通常用于線程。
CLONE_FS資源共享標志父子進程共享文件系統信息(如當前工作目錄、根目錄等)。
CLONE_FILES資源共享標志父子進程共享打開的文件描述符。
CLONE_SIGHAND資源共享標志父子進程共享信號處理程序和阻塞信號。
CLONE_PIDFD進程級別標志在父進程中為子進程創建一個 pidfd(PID文件描述符)。
CLONE_PTRACE進程級別標志允許追蹤繼續,父進程可以繼續對其子進程進行追蹤。
CLONE_VFORK進程級別標志父進程希望子進程在釋放其內存時喚醒父進程。
CLONE_PARENT進程級別標志子進程和父進程保持相同的父進程。
CLONE_THREAD線程/進程級別標志子進程和父進程屬于同一個線程組,通常用于線程。
CLONE_NEWNS命名空間相關標志創建一個新的掛載命名空間。
CLONE_SYSVSEM進程級別標志父子進程共享 System V 信號量(SEM_UNDO)語義。
CLONE_SETTLS線程級別標志為子進程創建新的 TLS(線程本地存儲)。
CLONE_PARENT_SETTID線程級別標志將線程標識符 (TID) 設置到父進程的 parent_tid 指向的位置。
CLONE_CHILD_CLEARTID線程級別標志線程退出時清除其 TID(線程標識符)。
CLONE_DETACHED進程級別標志已廢棄,忽略。
CLONE_UNTRACED進程級別標志如果設置了該標志,父進程不能強制對子進程進行追蹤。
CLONE_CHILD_SETTID線程級別標志子進程首次調度時將 TID 設置到 child_tid 指向的位置。
CLONE_NEWCGROUP命名空間相關標志創建一個新的 cgroup(控制組)命名空間。
CLONE_NEWUTS命名空間相關標志創建一個新的 UTS(UNIX時間共享)命名空間,通常用于主機名和域名的隔離。
CLONE_NEWIPC命名空間相關標志創建一個新的 IPC(進程間通信)命名空間。
CLONE_NEWUSER命名空間相關標志創建一個新的用戶命名空間,通常用于進程的用戶和組 ID 隔離。
CLONE_NEWPID命名空間相關標志創建一個新的 PID(進程標識符)命名空間。
CLONE_NEWNET命名空間相關標志創建一個新的網絡命名空間。
CLONE_IO進程級別標志子進程與父進程共享 I/O 上下文(I/O 調度等)。

2.2 創建進程系統調用

(1)fork(分叉):子進程是父進程的一個副本,采用了寫時復制的技術。
(2)vfork:用于創建子進程,之后子進程立即調用 execve 以裝載新程序的情況。為了避免復制物理頁,父進程會睡眠等待子進程裝載新程序。現在 fork 采用了寫時復制的技術,vfork 失去了速度優勢,已經被廢棄。
(3)clone(克隆):可以精確地控制子進程和父進程共享哪些資源。這個系統調用的
主要用處是可供 pthread 庫用來創建線程。
clone 是功能最齊全的函數,參數多,使用復雜,fork 是 clone 的簡化函數。


那么在執行這三個系統調用,實際執行的是do_fork函數,注意在當前(2025/4)最新linux版本6.9中do_fork被更換為kernel_clone(), 具體執行流程和do_fork大體相同,主要變更在kernel_clone 擴展了 do_fork 的功能,并且增加了更多針對不同類型進程創建的支持,特別是在 clone() 調用中引入了更多控制參數和特性。

1. do_fork流程——v6.9-kernel_clone

在v6.9版本的內核中,do_fork被替換取而代之的是kernel_clone,兩者核心流程類似
do_fork的流程

  1. 調用函數 copy_process 以創建新進程
  2. 關于第二個步驟中判斷CLONE_PARENT_SETTID的操作——CLONE_PARENT_SETTID:這是 clone() 調用中的一個標志,表示 父進程想要在子進程創建時將子進程的 PID 設置到某個指定位置。這個標志位指示內核將子進程的 PID 寫入父進程傳入的 parent_tid 指針。

具體作用:在一些特定的多線程應用或線程庫中,父進程或創建線程的控制者希望在用戶空間中直接獲得新創建線程(或進程)的 PID,便于后續的管理,比如設置線程的調度策略、處理進程間通信等。CLONE_PARENT_SETTID 可以幫助父進程或控制者直接獲取子進程的 PID,避免了額外的查詢操作。

  1. 調用函數 wake_up_new_task 以喚醒新進程。
  2. 如果是系統調用 vfork,那么當前進程等待子進程裝載程序。

2. do_fork中copy_process流程

創建fork新進程的主要工作由函數 copy_process 實現

官方注釋——只執行復制但是不啟動,state設置為TASK_NEW
This creates a new process as a copy of the old one, but does not actually start it yet.
It copies the registers, and all the appropriate parts of the process environment (as per the clone flags). The actual kick-off is left to the caller.
copy_process流程

接下來我們詳細解讀一下copy_process中每個流程

(1). 標志沖突判斷
  • CLONE_NEWNS & CLONE_FS:

    • CLONE_NEWNS 會創建一個新的掛載命名空間,意味著新的進程有一個獨立的根目錄(根文件系統)。而 CLONE_FS 是要求多個進程共享文件系統信息,包括根目錄。如果同時設置這兩個標志,會導致根目錄和文件系統信息沖突,因此是無效的。
  • CLONE_NEWUSER & CLONE_FS:

    • CLONE_NEWUSER 創建新的用戶命名空間,使得新的進程具有獨立的用戶身份。而 CLONE_FS 會共享文件系統信息,這會導致新進程在文件系統方面不獨立,違反了用戶命名空間的隔離原則,因此這兩個標志不能同時使用。
  • CLONE_THREAD & !CLONE_SIGHAND:

    • 線程組的進程必須共享信號處理程序。因此,當設置 CLONE_THREAD 時,必須設置 CLONE_SIGHAND 來共享信號處理程序。如果沒有設置 CLONE_SIGHAND,則無法確保線程組的一致性,導致沖突。
  • CLONE_SIGHAND & !CLONE_VM:

    • 當進程共享信號處理程序(CLONE_SIGHAND)時,必須共享虛擬內存空間(CLONE_VM)。如果不共享虛擬內存,信號處理程序會因進程間內存空間不同而無法正常工作,因此此組合會產生沖突。
  • CLONE_PARENT & SIGNAL_UNKILLABLE:

    • CLONE_PARENT 要求子進程的父進程為當前進程。全局 init 進程(init)是不可殺死的且沒有父進程,因此不允許全局 init 進程創建其他兄弟進程。否則,會違反進程樹結構,產生沖突。
  • CLONE_THREAD & (CLONE_NEWUSER | CLONE_NEWPID):

    • 線程不允許跨越用戶或 PID 命名空間。如果創建一個線程時,設置了 CLONE_NEWUSER 或 CLONE_NEWPID,則該線程將進入一個不同的命名空間,這會破壞線程組的共享,因此是無效的。
  • CLONE_PIDFD & CLONE_DETACHED:

    • 如果設置了 CLONE_PIDFD,表示父進程會持有子進程的 PID 文件描述符,允許父進程跟蹤子進程。而 CLONE_DETACHED 表示子進程是分離的,不需要父進程等待,因此不能同時設置這兩個標志。分離進程不應持有 PID 文件描述符。
(2). dup_task_struct——分配task空間

函數 dup_task_struct:函數 dup_task_struct 為新進程的進程描述符分配內存,把當前進程的進程描述符復制一份,為新進程分配內核棧。

內核棧——task_struct中的stack指向內核棧
內核棧布局

  1. 分配內核棧和 task_struct 所需空間

    • 每個進程在內核中有一塊私有棧(內核棧),和 task_struct 一起分配。
  2. 復制當前進程的 task_struct 數據到新結構體中

    • 這是“淺拷貝”,后續會由 copy_xxx() 函數根據CLONE_FLAG深拷貝處理(比如 copy_mm()、copy_files() 等)。
  3. 初始化調試字段、引用計數

    • 比如清除 task_struct->stack_canary,初始化調試狀態。
(3). 檢查用戶的進程數量限制

對于普通用戶:如果創建的進程數量超限,則失敗
對于根用戶:因為根用戶默認擁有忽略資源限制的權限(CAP_SYS_RESOURCE)和系統管理權限(CAP_SYS_ADMIN),可以創建

(4). copy_creds復制或共享證書

什么是 cred 證書?
回答 :
cred(全稱 struct cred)是 Linux 內核中用于描述進程安全相關信息的一種核心數據結構。它就是**“進程的身份證 + 安全通行證”,內核通過它判斷當前進程能不能干某件事**。


🔐 cred 結構體包含什么?

這個結構體定義在 include/linux/cred.h 中,里面包含了以下這些字段(簡化版):

字段含義
uid, gid實際用戶/組 ID
euid, egid有效用戶/組 ID
suid, sgid保存的用戶/組 ID(用于切換身份)
fsuid, fsgid文件系統相關的用戶/組 ID(用于訪問控制)
cap_inheritable可繼承的能力(capabilities)
cap_permitted被允許的能力
cap_effective當前生效的能力(實際起作用的)
cap_bsetbounding set,允許繼承的最大能力集合
user指向 struct user_struct,跟蹤用戶的資源使用(比如進程數)
security安全模塊使用(如 SELinux、AppArmor)

🧠 作用是什么?

內核中,幾乎所有需要安全判斷的操作,比如:

  • 訪問文件
  • 打開 socket
  • 調用某些系統調用(比如 mountkillptrace
  • 進入 namespace
  • 修改資源限制
  • 獲取 debug 權限(如 /proc/*

都會通過 current->cred 來做決策。

比如:

if (capable(CAP_SYS_ADMIN)) {// 允許系統管理操作
}

這里的 capable() 內部其實就是讀取當前線程的 cred->cap_effective,看看有沒有這個 capability。


🐾 誰用它?

除了內核自身判斷權限外,像:

  • ptrace()
  • setuid(), setgid()
  • capset()
  • LSM(如 SELinux)
  • 容器安全模型

都會操作或依賴 cred

一句話總結
cred是進程的安全身份信息,它決定了一個進程能干什么、能訪問什么、有沒有權限。


對于kernel_clone(do_fork)copy_cred() 如果設置了標志 CLONE_THREAD,即新進程和當前進程屬于同一個線程組,那么新進程和當前進程共享證書。
否則,復制cred。

在這里插入圖片描述


(5). 檢查線程數量限制

全局變量nr_threads 存放當前的線程數量;max_threads存放允許創建的線程最大數量,默認值是 MAX_THREADS。
如果線程數量達到允許的線程最大數量,那么不允許創建新進程。

(6). sched_fork——設置調度器相關參數
  1. 將task->state設為TASK_NEW,確保新進程不會被運行,也不會被信號喚醒不會被加入就緒隊列rq(runqueue)
  2. 把新進程的調度優先級設置為當前進程的正常優先級
    • 因為當前進程可能因為占有實時互斥鎖而被臨時提升了優先級
  3. unlikely檢查是否設置了SCHED_RESET_ON_FORK 標志,要求創建新進程時把新進程的調度策略和優先級設置為默認值
  4. 拒絕dl(dealline)任務fork
  5. SMP 多核支持初始化
(7). copy_xxx——根據CLONE_FLAG復制或共享資源

Linux 內核在創建新進程時執行的一系列子系統狀態復制流程,它的作用是將父進程的資源、狀態等復制或共享給子進程,以確保新進程具有完整的運行環境。
? 步驟及作用一覽表
5-10步驟中,只有相同線程組的線程間才會進行共享,人話:一個老爹生的

步驟函數調用作用失敗時回滾標簽
1perf_event_init_task(p, clone_flags)初始化 perf 事件監控(性能分析支持)bad_fork_sched_cancel_fork
2audit_alloc(p)初始化審計上下文,用于安全審計(audit 子系統)bad_fork_cleanup_perf
3shm_init_task(p)初始化與 System V 共享內存相關的結構無回滾(無失敗)
4security_task_alloc(p, clone_flags)安全模塊(如 SELinux)相關初始化bad_fork_cleanup_audit
5copy_semundo(clone_flags, p)復制 System V 信號量 undo 狀態bad_fork_cleanup_security
6copy_files(clone_flags, p, args->no_files)復制或共享文件描述符表(如 open filesbad_fork_cleanup_semundo
7copy_fs(clone_flags, p)復制或共享文件系統信息(如 cwd、root)bad_fork_cleanup_files
8copy_sighand(clone_flags, p)復制或共享信號處理器(signal handler)bad_fork_cleanup_fs
9copy_signal(clone_flags, p)復制或共享信號狀態(阻塞信號集等)bad_fork_cleanup_sighand
10copy_mm(clone_flags, p)復制或共享內存描述符(內存空間)bad_fork_cleanup_signal
11copy_namespaces(clone_flags, p)創建或共享命名空間(如 UTS、IPC、Mount 等)bad_fork_cleanup_mm
12copy_io(clone_flags, p)復制或共享 IO 上下文(如 IO調度器相關)bad_fork_cleanup_namespaces
13copy_thread(p, args)初始化線程狀態:棧、寄存器、TLS 等bad_fork_cleanup_io

3. do_fork中的wake_up_new_task流程

那么在結束copy_process流程后,一個新的進程或線程就創建成功了,接下來就是要去運行它,還記得在copy_process()/sched_fork()中將task->state置為TASK_NEW的作用嗎?那么在wake_up_new_task中把新進程的狀態從 TASK_NEW 切換到 TASK_RUNNING

在 SMP 系統上,創建新進程是執行負載均衡的絕佳時機,為新進程選擇一個負載最輕的處理器。


這時使用__set_task_cpu()將任務放到負載最輕的處理器上,實現負載均衡

流程:

  1. 調整state為running
  2. __set_task_cpu(),負載均衡
  3. 鎖rq
  4. 更新rq
  5. 釋放鎖

至此,一個新進程/線程的創建就正式結束了。

3. 進程的退出

3.1 退出概念簡介

退出,又分為

  • 主動退出
    • exit,exit_group
  • 被動退出
    • kill,tgkill 被信號通知退出

當進程退出的時候,根據父進程是否關注子進程退出事件,處理存在如下差異。
(1)如果父進程關注子進程退出事件,那么進程退出時釋放各種資源,只留下一個空的進程描述符,變成僵尸進程(即task_struct沒有被完全釋放)[因為系統需要保留一些關于子進程的信息,供父進程查詢(例如子進程的退出狀態)],發送信號 SIGCHLD(CHLD 是 child 的縮寫)通知父進程,父進程在查詢進程終止的原因以后回收子進程的進程描述符。
(2)如果父進程不關注子進程退出事件,那么進程退出時釋放各種資源,釋放進程描述符,自動消失。進程默認關注子進程退出事件,如果不想關注,可以使用系統調用 sigaction 針對信號SIGCHLD 設置標志 SA_NOCLDWAIT(CLD 是 child 的縮寫),以指示子進程退出時不要變成僵尸進程,或者設置忽略信號 SIGCHLD。

3.2 exit_group線程組退出

1. exit_group簡介

exit_group() 可以被看作是 信號傳遞式退出函數 的一種典型代表,它的語義是:終止整個線程組(即進程的所有線程)。

🧠 和普通 exit() 的區別:

函數影響范圍特點
exit()僅當前線程不會終止進程中其他線程
exit_group()當前線程 + 同一進程中的所有線程會向整個線程組中的所有線程發出終止信號

🧩 內核行為概覽

  • exit_group() 最終調用的是 do_group_exit()
  • 它會設置 signal->group_exit_code,標記線程組整體退出;
  • 然后會逐個 wake up 其他線程,讓它們也進入退出流程;
  • 所有線程會逐個進入 do_exit(),釋放資源、觸發鉤子等。

📦 為什么說它是“信號式”的?

盡管 exit_group() 本質是一個系統調用,但其實現通過內部機制模擬了類似“信號傳播”的退出方式: 通過共享的 struct signal_struct 對線程組成員**“廣播”退出狀態**,這就像是“向整個線程組傳遞了一個退出意圖”。

2. exit_group具體流程

exit_group流程
假設一個線程組有兩個線程,稱為線程 1 和線程 2,線程 1 調用 exit_group 使線程組退
出,線程 1 的執行過程如下。
(1)把退出碼保存在信號結構體的成員 group_exit_code 中,傳遞給線程 2。
(2)給線程組設置正在退出的標志。
(3)向線程 2 發送殺死信號,然后喚醒線程 2,讓線程 2 處理殺死信號。
(4)線程 1 調用函數 do_exit 以退出。
線程 2 退出的執行流程如下圖所示,線程 2 準備返回用戶模式的時候,發現收到
了殺死信號,于是處理殺死信號
,調用函數 do_group_exit,函數 do_group_exit 的執行過
程如下。
收到信號退出

3.3 kill

系統調用 kill(源文件“kernel/signal.c”)負責向線程組或者進程組發送信號。
(1)如果參數 pid 大于 0,那么調用函數 kill_pid_info 來向線程 pid 所屬的線程組發送信號。
(2)如果參數 pid 等于 0,那么向當前進程組發送信號。
(3)如果參數 pid 小于?1,那么向組長標識符為-pid 的進程組發送信號。
(4)如果參數 pid 等于?1,那么向除了 1 號進程和當前線程組以外的所有線程組發送信號。
在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/902544.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/902544.shtml
英文地址,請注明出處:http://en.pswp.cn/news/902544.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

人像面部關鍵點檢測

此工作為本人近期做人臉情緒識別,CBAM模塊前是否能加人臉關鍵點檢測而做的嘗試。由于創新點不是在于檢測點的標注,而是CBAM的改進,因此,只是借用了現成庫Dilb與cv2進行。 首先,下載人臉關鍵點預測模型:Index of /file…

【Python】每隔一段時間自動清除網站上cookies的方法

我在寫爬蟲的時候,經常會因為點擊瀏覽太多的頁面,而導致很多的cookies累積。 雖然單個Cookie很小,但長期積累可能占用瀏覽器存儲空間,導致瀏覽器運行變慢(尤其對老舊設備)。 而且Cookies(尤其…

非隔離電源芯片WT5104

非隔離電源芯片WT5104 非隔離電源芯片 WT5104 介紹 WT5104 是一款超高效且高精度的非隔離降壓開關電源恒壓控制驅動芯片,在各類電源轉換場景中提供5V輔助電源供電發揮著重要作用。 一、芯片特點 高集成度:內部集成 800V 功率 MOSFET,極大減…

基于 Python 的自然語言處理系列(83):InstructGPT 原理與實現

📌 論文地址:Training language models to follow instructions with human feedback 💻 參考項目:instructGOOSE 📷 模型架構圖: 一、引言:為什么需要 InstructGPT? 傳統的語言模型…

零基礎入門 Verilog VHDL:在線仿真與 FPGA 實戰全流程指南

摘要 本文面向零基礎讀者,全面詳解 Verilog 與 VHDL 兩大主流硬件描述語言(HDL)的核心概念、典型用法及開發流程。文章在淺顯易懂的語言下,配合多組可在線驗證的示例代碼、PlantUML 電路結構圖,讓你在 EDA Playground 上動手體驗數字電路設計與仿真,并深入了解從 HDL 編寫…

Kubernetes控制平面組件:API Server詳解(二)

云原生學習路線導航頁(持續更新中) kubernetes學習系列快捷鏈接 Kubernetes架構原則和對象設計(一)Kubernetes架構原則和對象設計(二)Kubernetes架構原則和對象設計(三)Kubernetes控…

云服務器存儲空間不足導致的docker image運行失敗或Not enough space in /var/cache/apt/archives

最近遇到了兩次空間不足導致docker實例下的mongodb運行失敗的問題。 排查錯誤 首先用nettools看下mongodb端口有沒有被占用: sudo apt install net-tools netstat --all --program | grep 27017 原因和解決方案 系統日志文件太大 一般情況下日志文件不會很大…

爬蟲學習——下載文件和圖片、模擬登錄方式進行信息獲取

一、下載文件和圖片 Scrapy中有兩個類用于專門下載文件和圖片,FilesPipeline和ImagesPipeline,其本質就是一個專門的下載器,其使用的方式就是將文件或圖片的url傳給它(eg:item[“file_urls”])。使用之前需要在settings.py文件中對其進行聲明…

拒絕用電“盲人摸象”,體驗智能微斷的無縫升級

🌟 為什么需要智能微型斷路器? 傳統斷路器只能被動保護電路,而安科瑞智能微型斷路器不僅能實時監測用電數據,還能遠程控制、主動預警,堪稱用電安全的“全能衛士”!無論是家庭、工廠還是商業樓宇&#xff0…

如何優雅地為 Axios 配置失敗重試與最大嘗試次數

在 Vue 3 中,除了使用自定義的 useRequest 鉤子函數外,還可以通過 axios 的攔截器 或 axios-retry 插件實現接口請求失敗后的重試邏輯。以下是兩種具體方案的實現方式: 方案一:使用 axios 攔截器實現重試 實現步驟: 通…

【Leetcode刷題隨筆】242.有效的字母異位詞

1. 題目描述 給定兩個僅包含小寫字母的字符串 s 和 t ,編寫一個函數來判斷 t 是否是 s 的 字母異位詞。 字母異位詞定義:兩個字符串包含的字母種類和數量完全相同,但順序可以不同(例如 “listen” 和 “silent”)。 …

示例:spring xml+注解混合配置

以下是一個 Spring XML 注解的混合配置示例,結合了 XML 的基礎設施配置(如數據源、事務管理器)和注解的便捷性(如依賴注入、事務聲明)。所有業務層代碼通過注解簡化,但核心配置仍通過 XML 管理。 1. 項目結…

Crawl4AI:打破數據孤島,開啟大語言模型的實時智能新時代

當大語言模型遇見數據饑渴癥 在人工智能的競技場上,大語言模型(LLMs)正以驚人的速度進化,但其認知能力的躍升始終面臨一個根本性挑戰——如何持續獲取新鮮、結構化、高相關性的數據。傳統數據供給方式如同輸血式營養支持&#xff…

【機器學習-周總結】-第4周

以下是本周學習內容的整理總結,從技術學習、實戰應用到科研輔助技能三個方面歸納: 文章目錄 📘 一、技術學習模塊:TCN 基礎知識與結構理解🔹 博客1:【時序預測05】– TCN(Temporal Convolutiona…

Mysql--基礎知識點--79.1--雙主架構如何避免回環復制

1 避免回環過程 在MySQL雙主架構中,GTID(全局事務標識符)通過以下流程避免數據回環: 1 事務提交與GTID生成 在Master1節點,事務提交時生成一個全局唯一的GTID(如3E11FA47-71CA-11E1-9E33-C80AA9429562:2…

安寶特科技 | AR眼鏡在安保與安防領域的創新應用及前景

隨著科技的不斷進步,增強現實(AR)技術逐漸在多個領域展現出其獨特的優勢,尤其是在安保和安防方面。AR眼鏡憑借其先進的功能,在機場、車站、海關、港口、工廠、園區、消防局和警察局等行業中為安保人員提供了更為高效、…

Linux第十講:進程間通信IPC

Linux第十講:進程間通信IPC 1.進程間通信介紹1.1什么是進程間通信1.2為什么要進程間通信1.3怎么進行進程間通信 2.管道2.1理解管道2.2匿名管道的實現代碼2.3管道的五種特性2.3.1匿名管道,只能用來進行具有血緣關系的進程進行通信(通常是父子)2.3.2管道文…

微信小程序通過mqtt控制esp32

目錄 1.注冊巴法云 2.設備連接mqtt 3.微信小程序 備注 本文esp32用的是MicroPython固件,MQTT服務用的是巴法云。 本文參考巴法云官方教程:https://bemfa.blog.csdn.net/article/details/115282152 1.注冊巴法云 注冊登陸并新建一個topic&#xff…

SQLMesh隔離系統深度實踐指南:動態模式映射與跨環境計算復用

在數據安全與開發效率的雙重壓力下,SQLMesh通過動態模式映射、跨環境計算復用和元數據隔離機制三大核心技術,完美解決了生產與非生產環境的數據壁壘問題。本文提供從環境配置到生產部署的完整實施框架,助您構建安全、高效、可擴展的數據工程體…

Spring Data詳解:簡化數據訪問層的開發實踐

1. 什么是Spring Data? Spring Data 是Spring生態中用于簡化數據訪問層(DAO)開發的核心模塊,其目標是提供統一的編程模型,支持關系型數據庫(如MySQL)、NoSQL(如MongoDB)…