【Note】《深入理解Linux內核》 第二十章:深入理解 Linux 程序執行機制

《深入理解Linux內核》 第二十章:深入理解 Linux 程序執行機制(Program Execution)

關鍵詞:exec 系列系統調用、可執行文件格式(ELF)、用戶地址空間、內存映射、動態鏈接、棧初始化、入口點、共享庫、內核態與用戶態切換


一、概述:程序是如何被執行的?

1.1 本質

Linux 中,“程序執行”是指某個已存在的進程調用 exec() 系列系統調用后,由內核將該進程的上下文替換為另一個程序的上下文,從而在相同 PID 下運行新的程序。

fork() 創建新進程不同,exec() 并不創建新進程,而是替換現有進程的地址空間。

1.2 系統調用家族

int execl(const char *path, const char *arg, ..., NULL);
int execv(const char *path, char *const argv[]);
int execle(const char *path, const char *arg, ..., NULL, char *const envp[]);
int execve(const char *filename, char *const argv[], char *const envp[]);

內核中的入口點為:

SYSCALL_DEFINE3(execve, const char __user *, filename,const char __user *const __user *, argv,const char __user *const __user *, envp)

二、從用戶態到內核態

2.1 用戶空間的 execve()

程序調用 exec 函數族(如 execv())最終都會轉換為 execve() 系統調用。

其傳入參數包括:

  • 程序路徑 filename
  • 命令行參數 argv
  • 環境變量 envp

2.2 內核入口

系統調用處理流程:

  1. 用戶態調用 execve;
  2. CPU 切換到內核態;
  3. 內核從系統調用表中查找 sys_execve()
  4. 調用 do_execve()do_execveat_common()
  5. 進入真正的程序替換邏輯。

三、execve 內核實現流程

程序執行的內核主干邏輯如下:

do_execveat_common()└── exec_binprm()└── search_binary_handler()└── load_elf_binary() 或其他格式

3.1 創建 binprm 結構

struct linux_binprm {char buf[BINPRM_BUF_SIZE];struct file *file;...
};
  • 包含傳入參數、程序路徑;
  • 讀取前128字節,判斷文件格式;
  • 設置執行權限、清除信號等。

3.2 判斷可執行文件格式

執行 search_binary_handler()

  • 檢查 ELF 標志(前4字節為 0x7f + ELF);
  • 若是腳本(以 #! 開頭),調用 load_script()
  • 若是 ELF 文件,調用 load_elf_binary()

四、加載 ELF 可執行文件

4.1 ELF 文件結構

ELF(Executable and Linkable Format)是 Linux 下標準的可執行文件格式。

主要結構:

ELF Header
|
+-- Program Header Table (段表)
|
+-- Section Header Table (僅編譯調試時使用)
|
+-- 數據段、代碼段、堆、符號表等
  • ELF Header:描述整個文件;
  • Program Header Table:決定哪些段需要加載;
  • 每個段描述:起始地址、偏移、大小、屬性(可執行、可寫等)。

4.2 ELF 加載流程

load_elf_binary() 實現步驟:

  1. 驗證 ELF 魔數;
  2. 解析 Program Header Table;
  3. 使用 do_mmap() 映射段到用戶地址空間;
  4. 設置 mm->start_codestart_databrk
  5. 初始化用戶棧;
  6. 設置 e_entry(程序入口點);
  7. 調用 start_thread() 設置寄存器(EIP / RIP);
  8. 切換到用戶態開始執行。

五、構建新用戶地址空間

5.1 mm_struct 的替換

每個進程都有一個 mm_struct

struct mm_struct {struct vm_area_struct *mmap;struct pgd_t *pgd;...
};

當調用 execve 時,原有的地址空間會被釋放(mm_release()),新的 mm_struct 被創建并綁定。

5.2 do_mmap 的作用

調用 do_mmap() 將 ELF 段映射到用戶空間:

  • .text 映射為可執行段;
  • .data 映射為可寫段;
  • .bss 用于初始化堆;
  • 其他段如 .rodata 也被映射;

mmap 映射區域都以 vm_area_struct 記錄,最終組成進程虛擬內存布局。


六、用戶棧與參數傳遞

6.1 參數與環境變量的拷貝

exec 調用時會將 argvenvp 拷貝到內核緩沖區,再構建用戶棧:

  • 棧頂:參數數量 argc;
  • 緊接著:argv 指針數組;
  • 然后:envp 指針數組;
  • 最后是 NULL terminator;

6.2 棧構建邏輯

setup_arg_pages()
create_elf_tables()
  • 將參數字符串數據拷貝到用戶棧;
  • 設置 AT_PHDRAT_ENTRY 等 auxv;
  • 創建適配動態鏈接器的數據結構(如 ld.so);

七、動態鏈接與共享庫加載

7.1 動態鏈接器的作用

如果 ELF 是動態鏈接的,其 PT_INTERP 段指定了動態鏈接器(如 /lib/ld-linux.so.2)。

流程:

  1. 加載主 ELF 文件;

  2. 加載動態鏈接器;

  3. 動態鏈接器運行在用戶態,負責:

    • 加載所需 .so 文件;
    • 執行符號解析與重定位;
    • 最終跳轉到 main() 函數。

7.2 預加載庫

環境變量:

LD_PRELOAD=/lib/myhook.so ./app

可在程序啟動前注入庫,進行函數劫持等操作。


八、執行權限與文件檢查

8.1 權限驗證

  • 檢查可執行文件是否有執行權限;
  • 檢查是否可讀取;
  • 判斷 SUID/SGID 是否生效;
  • 對腳本文件,檢查 #! 指向的解釋器;

8.2 setuid 程序執行注意點

當可執行文件具有 SUID 權限時:

  • 進程會提升有效 UID 為目標用戶;
  • 內核需清除大部分內存內容,防止信息泄漏;
  • 需要設置 secureexec 標志位,屏蔽某些危險變量(如 LD_PRELOAD);

九、執行結果與返回路徑

9.1 執行完成前的最后一步

  • 在 execve 完成所有加載后,調用 start_thread() 設置 PC/SP;
  • 切換到用戶態入口點開始執行;
  • 若失敗,則返回錯誤碼。

9.2 execve 成功永不返回

一旦 execve 成功,舊進程空間完全被新程序替換,除非失敗,調用永不返回。


十、文件格式支持機制(binfmt)

Linux 支持多種可執行文件格式(ELF, a.out, scripts, Java 等):

struct linux_binfmt {int (*load_binary)(struct linux_binprm *);int (*load_shlib)(struct file *);...
};

常見格式注冊:

  • register_binfmt(&elf_format);
  • register_binfmt(&script_format);

這些接口掛載在 search_binary_handler() 中被遍歷查找處理程序。


十一、源碼路徑與調試技巧

路徑說明
fs/exec.cexecve 核心邏輯
fs/binfmt_elf.cELF 加載實現
fs/binfmt_script.c腳本執行邏輯
arch/x86/kernel/process.c架構相關 start_thread() 實現
include/linux/binfmts.hbinfmt 接口定義
/proc/self/maps當前進程地址空間布局查看

調試工具:

  • strace ./a.out:追蹤 execve 執行;
  • readelf -a ./a.out:查看 ELF 內容;
  • lsof -p PID:查看進程打開的文件;
  • gdb:調試執行流程與鏈接器行為。

十二、小結

  • execve 系統調用是 Linux 執行程序的核心;
  • 內核根據 ELF 或腳本格式加載目標程序;
  • 構建新的用戶空間,包括棧、段映射、鏈接器加載;
  • 支持 SUID、環境變量注入、安全過濾;
  • 動態鏈接器負責完成后續 .so 加載與符號重定位;
  • 內核中設計清晰,分層合理,是內核與用戶交互的關鍵橋梁。

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

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

相關文章

服務器如何配置防火墻規則以阻止惡意流量和DDoS攻擊?

防火墻是保護服務器免受惡意流量和 DDoS 攻擊的第一道防線。通過合理配置防火墻規則,可以有效阻止惡意訪問、限制不必要的流量,并減少攻擊對服務器的影響。以下是配置防火墻規則的全面指南,包括基礎規則設置、防御 DDoS 攻擊的高級策略和最佳…

持續性投入是成就自我價值的關鍵一環

概述 時間,的唯一公平之處就是給你我的長度是相同的,這也是它唯一公平,也是不公平的地方。 所謂的公平,就是不患寡而患不均中所說的平均。 所謂的不公平就是,相同時間內我們彼此對應的標價不同,延伸到后…

使用allegro在BoardGeometry的Silkscreen_Top層畫出圖案

目錄 1. 圖形及圖形放置顯示2. 繪制 1. 圖形及圖形放置顯示 繪制完成圖案: 導出后圖案: 2. 繪制 圖層選中; 畫圓型; 半徑3.5mm,原點生成; 在圖案中挖空; 用指令走線: …

Kotlin 協程:Channel 與 Flow 深度對比及 Channel 使用指南

前言 在 Kotlin 協程的異步編程世界里,Channel 和 Flow 是處理數據流的重要工具,它們有著不同的設計理念與適用場景。本文將對比二者功能與應用場景,詳細講解 Channel 的使用步驟及注意事項 。 一、Channel 與 Flow 的特性對比 Channel 是協程…

MYsql主從復制部署

MySQL 主從復制是將主數據庫的變更自動同步到從數據庫的過程,常用語讀寫分離、高可用性和數據備份。 1.環境準備 確保主從服務器已安裝相同版本的 MySQL,并能通過網絡互相訪問。 # 檢查 MySQL 版本 mysql -V 2.配置主服務器 (1&#xff0…

安燈呼叫看板如何實現汽車生產異常秒級響應

在汽車零部件工廠的靜置車間,傳統生產管理依賴人工巡檢與紙質記錄,存在效率低、信息滯后、異常響應慢等問題。某汽車廠曾因物料靜置時間未及時監控,導致批次混料,損失超10萬元。而安燈呼叫看板系統的引入,通過實時狀態…

構造函數注入在spring boot 中怎么使用詳解

我們來詳細講解一下在 Spring Boot 中如何使用構造函數注入,并通過一個完整的、可運行的例子來演示。 構造函數注入是 Spring 官方最推薦的依賴注入方式,因為它能保證對象的不可變性和依賴的完整性。 核心理念 在 Spring Boot 中使用構造函數注入非常簡單…

2025.6.30-2025.7.06第26周:第一次參加頭馬演講俱樂部

現在是周一早上6:23,我開始寫上周的周總結。 3件超出預期的事 參加頭馬俱樂部絕對是最超出預期的,使得這個周末格外的快樂簡歷的第一版終于改完了,花了好長的時間,其中有一天心情還很蕩,因為,我想&#x…

2025使用VM虛擬機安裝配置Macos蘋果系統下Flutter開發環境保姆級教程--下篇

其實如何安裝VM,如何安裝MACOS網上的教程很多,我只是結合我的體驗重新整理了一次,接下來才進入本教程最核心的部分,Flutter開發環境的配置部分。、一.配置前準備 主要是準備相應的工具包,以及其他虛擬機設置1.工具包 工具包的版本也可以自行配置,我這主要是我使用的是F…

QSPI、OSPI與FSMC的區別與內存映射分析

QSPI、OSPI與FSMC的區別與內存映射分析 基本概念與區別 1. FSMC (靈活靜態存儲控制器) 接口類型:并行接口,通常8/16位數據總線總線標準:傳統并行總線協議速度:相對較低,通常最高約100MHz應用場景:SRAM、NOR…

系統思考與心智模式探索

成長的真正障礙,不是能力的不足,而是看待問題的局限。 在復雜多變的商業環境中,我們往往習慣于解決“眼前”的問題,卻忽視了深藏背后的系統性障礙。我們看到的只是表面的“癥狀”,而真正的根源,卻往往隱藏…

物聯網技術的關鍵技術與區塊鏈發展趨勢的深度融合分析

一、物聯網技術的核心架構與關鍵技術 物聯網技術體系由感知層、網絡層、平臺層、應用層和安全層構成,各層技術協同工作,實現物理世界與數字世界的深度融合。 感知層:物聯網的“感官” 傳感器技術:包括環境傳感器(溫度…

針對Exhcnage Server的攻擊防范措施

一、背景介紹最近,安全研究人員揭露了一個名為 NightEagle(又名 APT-Q-95) 的高級持續性威脅(APT)組織。這個組織被觀察到利用 Microsoft Exchange 服務器中的零日漏洞鏈 進行攻擊,其主要目標是中國政府、國…

編程基礎:繼承

能幫到你的話,就給個贊吧 😘 文章目錄繼承:使用基類成員:前提——派生類必須同樣支持基類成員(組件和功能)示例:動物Animal 有 鰓 和 會飛。則 鳥Bird 不是 Animal,因為Bird雖會飛,卻沒有鰓。魚…

TMC4361A 使用(未驗證)

prompt 我用STM32F103C8T6 來控制 TMC4361A 運動控制芯片 ,我配置 STM32F103C8T6 的 SPI1 與 TMC4361A 進行通信,配置 PA4 作為片選線,配置 PA8 作為 RCC_MCO 輸入時鐘輸入到 TMC4361A, 并將其連接到TMC4361A的CLK_EXT引腳。我想控制 TMC4361…

深度剖析:如何解決Node.js中mysqld_stmt_execute參數錯誤

在Node.js后端開發中,使用mysql2等數據庫驅動與MySQL/MariaDB交互時,Incorrect arguments to mysqld_stmt_execute 是一個令人頭疼的錯誤。它通常意味著你傳遞給SQL預處理語句的參數數量與SQL字符串中問號(?)占位符的數量不匹配。…

Vue3 學習教程,從入門到精通,Vue 3 安裝指南及語法知識點詳解(2)

Vue 3 安裝指南及語法知識點詳解 本文將詳細介紹 Vue 3 的所有安裝方式,并深入講解 Vue 3 的語法知識點。此外,還將提供一些綜合性案例,展示如何綜合運用 Vue 3 的各項功能。一、安裝 Vue 3 的所有方式 Vue 3 提供了多種安裝方式,…

C++基礎復習筆記

一、數組定義 在C中,數組初始化有多種方式,以下是常見的幾種方法: 默認初始化 數組元素未顯式初始化時,內置類型(如int、float)的元素值未定義(垃圾值),類類型調用默認構…

手機和PC遠控安全深度測評:TeamViewer/ToDesk/向日葵安全防線對比

聲明:本測試報告系作者基于個人興趣及使用場景開展的非專業測評,測試過程中所涉及的方法、數據及結論均為個人觀點,不代表任何官方立場或行業標準。 一、引言 當下遠程控制技術已深度融入大眾的工作與生活,無論是上班族在家操…

Windows 11的開始菜單調整為左下角布局

1.桌面右鍵個性化 2.個性化中任務欄 3.任務欄選擇任務欄行為 4.任務欄行為中 任務欄對齊方式選擇靠左即可