(2021) 18 [代码讲解] 可执行文件
(2021) 18 [代碼講解] 可執(zhí)行文件
南京大學操作系統(tǒng)課蔣炎巖老師網(wǎng)絡課程筆記。
視頻:https://www.bilibili.com/video/BV1HN41197Ko?p=18
講義:http://jyywiki.cn/OS/2021/slides/C8.slides#/
背景
回顧
程序 = 狀態(tài)機
- 狀態(tài)機執(zhí)行 = 狀態(tài)機上的路徑
- 狀態(tài)機管理API:
- fork - 復制
- execve - 重置
- exit - 終止
狀態(tài)機 = 可執(zhí)行文件
一直以來 “最神秘” 的一種文件,雙擊即可打開,這時為什么?
本次課的內(nèi)容與目標
理解靜態(tài)鏈接的可執(zhí)行文件
- 可執(zhí)行文件的加載
- xv6加載器
可執(zhí)行文件的加載
小知識:可執(zhí)行文件 不等同于 ELF文件
考慮腳本文件,它也是可執(zhí)行文件:
#!/bin/bash -x echo Hello #!/usr/bin/env python3 print('Hello') #!./a.out為什么是/usr/bin/env?
-
因為 #! 需要絕對路徑 (背后是 execve)
-
Shebang 究竟發(fā)生了什么?
- 不妨 strace 一下!
可以參考筆者的這篇博客:Linux中的二進制可執(zhí)行文件和腳本可執(zhí)行文件及Shebang。
進程(ELF)初始化
虛假的進程(ELF)初始化
execve(path, argc, envp):重置一個狀態(tài)機,為它傳入?yún)?shù)argv和envp,概念好理解,但究竟什么叫 傳入?
我們知道程序(狀態(tài)機)的狀態(tài)無非就是保存在寄存器或者內(nèi)存中(M,G),傳入?yún)?shù)肯定是傳到了內(nèi)存的某個地方,但究竟是哪里呢?
一定要能靜下心來讀手冊,多嘗試去靜下心來去手冊,很快就能適應它了。 RTFM
-
[System V ABI (x86-64)][http://jyywiki.cn/pages/OS/manuals/sysv-abi.pdf]
Section 3.4: Process Initialization
- 之前用 gdb 調(diào)試過 “初始狀態(tài)”
- 看到了寄存器的初始值
- 手冊完整規(guī)定了 execve 后的進程狀態(tài)
- libc 會使用它
- 根據(jù) ABI,你可以開發(fā)自己的 libc !
- libc 會使用它
- 之前用 gdb 調(diào)試過 “初始狀態(tài)”
-
Gitlab repo
挑戰(zhàn):不使用 execve 加載 ELF
理論上把可執(zhí)行文件 (ELF) 指定的數(shù)據(jù)搬運到內(nèi)存,就可以實現(xiàn)二進制文件的加載。
試一試?loader.zip: 加載靜態(tài)鏈接的 ELF (glibc)
execve 本質(zhì)上是 “多余” 的,只要我們能按照手冊,把可執(zhí)行文件中的內(nèi)容正確地搬運到內(nèi)存中,就可以替換掉execve。
- 可以用 mmap/munmap + 一小段 trampoline code 實現(xiàn)
- 這個系統(tǒng)調(diào)用可以被庫函數(shù) (和其他系統(tǒng)調(diào)用) “模擬”
模擬系統(tǒng)調(diào)用(1):互相模擬,互相傷害
既然完全可以 “自己加載” 可執(zhí)行文件。我們也可以在一個操作系統(tǒng)里實現(xiàn)另一個操作系統(tǒng)的 API 啊,只要能夠在本系統(tǒng)內(nèi)模擬另一個系統(tǒng)的系統(tǒng)調(diào)用就行。指令面前系統(tǒng)平等 (Linux, Windows, …)。
WSL (Windows Subsystem for Linux)
- Windows 執(zhí)行 ELF64; 在 Windows 中實現(xiàn) Linux 系統(tǒng)調(diào)用
Wine (POSIX Subsystem for Windows 😂)
- 支持 Windows PE (Portable Executable) 格式
- 實現(xiàn) Windows API (Overview)
模擬系統(tǒng)調(diào)用(2):把系統(tǒng)調(diào)用挪到用戶空間
操作系統(tǒng)可以只提供一組最基本的硬件層的抽象(如mmap)。其他的全都交給應用程序。
“微內(nèi)核” (Microkernel)
- 操作系統(tǒng)只提供非常有限的 API 和權(quán)限管理
- 進程/線程創(chuàng)建和通信
- 內(nèi)存映射
- 設備寄存器
- 其他都實現(xiàn)在用戶程序
- 例如內(nèi)核里沒有文件系統(tǒng)
- 想打開文件?發(fā)消息給服務器吧
“外核” (Exokernel)
- 操作系統(tǒng) = 庫函數(shù)
- 一個硬件上可以跑多個 libOS
灌雞湯:《操作系統(tǒng)》這門課究竟學什么?
相比知識點本身,獲得知識的方法和對系統(tǒng)的掌控力更重要。
本課程想要帶給大家的:
狀態(tài)機視角
- 程序 = 狀態(tài)機
- 操作系統(tǒng) = 狀態(tài)機的虛擬化
機器永遠是對的
- 只要按照 spec 實現(xiàn),就絕對能 work
- 地址空間里的每一個地址都有解釋 (vdso, vvar, …)
- CPU: 指令實現(xiàn)對了,仙劍就能跑、操作系統(tǒng)就能跑
- System-V ABI: 實現(xiàn)對了,不用 execve 也可以加載可執(zhí)行文件
xv6 加載器
- TODO
總結(jié)
本次課內(nèi)容與目標
- 理解靜態(tài)鏈接的可執(zhí)行文件
- 可執(zhí)行文件的加載
- xv6 加載器
Take-away messages
- RTFM; RTFSC
- 紙面上的理解都是片面的
總結(jié)
以上是生活随笔為你收集整理的(2021) 18 [代码讲解] 可执行文件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: nst股票是什么意思
- 下一篇: uc3842改可调电源教程_明纬开关电源