南京大學OS筆記(1)-應用眼中的操作系統
早就想刷一刷南大JYY老師的os課。之前稍微看過幾節,果然講的風趣幽默,而且現場寫代碼展示水平確實很高,這次准備認真刷一刷然后好好記一下筆記。當然lab就不做了,因為已經做過mit的lab了。刷課主要是為了復習基礎知識和學的更深入一點。第一節操作系統歷史就不記筆記了,直接從第二節開始
1. 什么是應用程序
1. (應用)程序

這里學到和csapp里的一致的。下面看一系列代碼演示

當我gcc -c a.c的時候會生成一個a.o。注意-c表示編譯。這里的a.o是可重定位目標文件。而不是可執行目標文件。

而在執行gcc a.o就會把它變成一個可執行目標文件。這里我在我自己的Linux機器上報錯了。

總結一下,程序就是可執行的二進制文件,無論什么程序在Linux系統下都是如此的。
2. ELF二進制文件

正因如此,我們可以用vim直接打開/bin/ls

這是一個二進制文件,所以這里直接顯示亂碼。
xxd可以用來讀二進制文件

這里的Entry point address表示它第一條指令的起始地址。
3. 最簡單的" Hello World"
1. 如果我們有一個下面這樣的代碼
int main () {
printf("Hello World\n");
}
可以直接運行嗎。看起來沒什么問題,但我們試試

-
這里會提示我們沒有定義
puts,明明是調用了printf為什么會提示puts這是因為printf在底層實際上調用了puts這是因為gcc即便在沒有設置優化的情況下。也就是
- o0的情況下還是會做優化,把printf簡化成了puts -
第二個問題是這里提示了warninng是我們沒有制定代碼的起始位置
2. 如果我們再嘗試一次代碼
int main() {
}
這是一個完全空的代碼。但是它還是會報錯

我們需要用gdb調試一下,看看到底為什么出錯了

我們需要單步執行,執行到retrun這里。return指令就是調用main函數的地方。

因此在這里我們觸發了段錯誤。這里我們不能訪問地址為1的地方
3. 正確的嘗試
這里jyy老師引入了一段匯編代碼。讓hello程序變得正確


這里單步執行到了系統調用
%eax 傳遞系統調用號
%rdi 傳遞第一個參數 ,以此類推
2. 應用程序怎么調用操作系統
1.首先看一下syscall的代碼在哪里

objdump指令解釋
Displays information about one or more object files.
這里可以發現我們所有的系統調用都是callq syscall@plt-動態鏈接來自於libc的代碼
2. Main()之前發生了什么?
(面試題)一個普通的C程序第一條指令子啊哪里?
- ❌ main的第一條指令
- ❌ libc的_start

可以用gdb調試一下會發現。它的第一條指令會在lib64/ld-linux-x86-64.so這是操作系統自帶的加載器
下面輸入info inferiors看一下有什么問題
- 我們發現我們現在運行的這個程序進程號是12305。
- 我們使用
pmap 12305輸出這個進程的信息。

會發現os已經幫我們做了很多事情所以整個過程是
os自帶的加載器---> 加載libc------> 加載a.out
看下面這個程序。

雖然main是空的。,但是這里的
Hello World
Goodbye, Cruel OS World
還是可以正常輸出
3. Trace的使用
使用strace可以追蹤系統調用

這里跟隨課上jyy老師的腳步分析一下a.out的系統調用
- 可以發現第一條系統調用是
execve - 然后libc執行了一堆系統調用
- 最后才會到我們自己寫的程序
3. 應用眼中的操作系統

可以說所有的程序都是類似的,不斷的調用系統調用。從開始到關閉
1. gcc的系統調用過程

-
這里的gcc確實是先利用as來做編譯
-
然后用collect2來做鏈接

collect2主要用來做合成,會把構造器和析構器的代碼生成出來

- 在gcc的最后會調用ld。

2. 其他的應用程序

