精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

程序是如何運行起來的

開發 前端
相信很多同學都會有疑問,一個程序是如何運行起來的,為什么我們在shell中執行了一個程序,它的main函數就會被調用呢?在main函數被調用之前及之后,又經歷了什么呢?

[[383987]]

 

 

因為圖片比較大,微信公眾號上壓縮的比較厲害,所以很多細節都看不清了,我單獨傳了一份到github上,想要原版圖片的,可以點擊下方的閱讀原文,或者直接使用下面的鏈接,來訪問github:

https://github.com/wangyuntao/linux-kernel-illustrated

另外,精致全景圖系列文章,以及之后的linux內核分析文章,我都會整理到這個github倉庫里,歡迎大家star收藏。

相信很多同學都會有疑問,一個程序是如何運行起來的,為什么我們在shell中執行了一個程序,它的main函數就會被調用呢?在main函數被調用之前及之后,又經歷了什么呢?

今天我們就來詳細的說下這個問題。

還是和之前一樣,我畫了一張程序運行的全景圖,在上圖中,一個程序運行所經歷的代碼段,我都標注了其所在的git倉庫、源文件、及函數名,想要自己看源碼的,可以參考下上圖中的這些信息。

我們先從整體上講一下這張圖。

在linux下,我們一般都是通過shell來執行程序的。

shell其實也是一個普通的程序,它也有自己的main函數,它在正常運行后,會通過調用read_command函數,來等待用戶輸入命令。

在接收到用戶輸入的命令后,shell會先使用fork系統調用,創建一個子進程,然后再在這個子進程中,通過execve系統調用,執行最終的用戶程序。

在子進程執行用戶程序期間,shell主進程會調用waitpid函數,阻塞等待子進程的完成,子進程完成之后,waitpid從阻塞狀態中返回,且status參數中會帶著子進程的退出碼,這個退出碼會在后續的邏輯中被保存起來,供用戶查詢。

之后,shell主進程進入到下一次循環,繼續等待用戶輸入命令并執行。

以上就是shell的主體邏輯,對應于上面全景圖中的藍色部分。

下面我們再來看下linux內核中有關execve系統調用的代碼,也就是上面全景圖中的綠色部分。

shell通過execve系統調用,告知linux內核,要在當前進程中執行目標程序,linux內核經過層層代碼,最終到達load_elf_binary函數。

該函數是整個系統調用中最核心的一段邏輯,它主要用來為目標程序準備各種執行環境。

比如,映射代碼區、數據區等到當前進程的虛擬地址空間,將程序名、環境變量、程序參數、及各種其他數據,有規律的壓入到新分配的棧中,等等。

之后,load_elf_binary函數會調用start_thread,進而會調用start_thread_common函數。

在該函數里,會將返回到用戶區之后,要執行的,用戶區程序的起始地址,設置到regs->ip里,同時也會將上面新初始化好的,用戶堆棧的棧頂地址,設置到regs->sp里。

當execve系統調用返回到用戶區之后,regs->ip和regs->sp里的值,會分別賦值到rip和rsp寄存器里,這樣指定的用戶程序就可以繼續執行了。

這一流程我們在之前的文章 精致全景圖 | 系統調用是如何實現的 中講過,這里就不再贅述。

不過這里還是有一點需要注意,就是設置到regs->ip中的地址,并不是我們自己程序的起始地址,而是動態鏈接器 /lib64/ld-linux-x86-64.so.2 的起始地址。

之所以要設置動態鏈接器的起始地址,是因為我們需要在返回到用戶區之后,讓其可以繼續為我們的程序準備執行環境,比如,幫忙加載程序依賴的各種動態鏈接庫等。

在動態鏈接器為我們的程序準備好執行環境之后,它會從進程堆棧的auxiliary vector區,取出最終用戶程序的真正起始地址,并跳轉到該位置開始執行。

auxiliary vector區存放的用戶程序的起始地址,是上面linux內核初始化堆棧時設置的。

動態鏈接器相關的代碼就是這些,它對應于上面全景圖中紫色的部分。

在跳轉到我們自己程序的起始地址后,首先執行的并不是我們寫的main函數,而是glibc里名為_start的一段匯編代碼。

這段匯編代碼也比較簡單,主要是從堆棧中獲取main函數所需的argc,argv等參數,然后最終調用我們寫的main函數。

當main函數返回之后,glibc里的后續代碼,會將main函數的返回值,當作該進程的退出碼,然后調用exit結束該進程。

這些代碼對應于上面全景圖中的粉色部分。

進程調用exit退出之后,shell主進程也會從waitpid的阻塞狀態中返回,然后繼續進行下一次循環。

以上就是程序完整的啟動和結束流程。

下面我們來看下具體的源碼實現。

注意,為了方便理解,很多代碼我們都做了刪減。

首先是shell部分,shell是一個普通的程序,它也有自己的main函數:

 

該函數里調用了reader_loop:

 

reader_loop的主體邏輯是,在while循環里不斷的使用read_command函數讀取用戶輸入的命令,然后使用execute_command執行該命令。

execute_command函數經過層層代碼后,會使用下圖中的fork,創建一個子進程:

 

然后在該子進程中,使用execve系統調用,告知linux內核,用當前子進程執行新的用戶程序:

 

在shell主進程中,會調用waitpid函數,阻塞等待子進程的完成:

 

當子進程退出后,waitpid會從阻塞狀態中返回,并在status里攜帶子進程的退出碼,之后shell主進程又返回上面的read_command函數,繼續等待用戶下一條命令的輸入。

以上就是bash的主體邏輯,對應于上面全景圖中的藍色部分。

下面我們繼續看全景圖中的綠色部分,也就是linux內核中有關execve的代碼。

當shell的子進程執行execve函數時,linux內核中對應的系統調用被觸發:

 

沿著函數的調用鏈,我們會找到一個名為do_execveat_common的函數,在該函數中,會將目標程序的文件名、環境變量、及各種程序參數等字符串,拷貝到新創建的用戶堆棧區:

 

此時,新創建的堆棧區里內容,就如上面全景圖中右下角的a1-a9, b1-b8部分構成的二維網格區域里所示的內容。

其中,黃色區域里存放的是程序參數 ./a.out hello world,藍色區域里存放的是環境變量 SHLVL=2, HOME=/, TERM=linux, PWD=/,橘黃色區域里存放的是要執行的程序文件名 ./a.out。

這些內容和我們執行的測試程序,及其所處的環境也正好一樣:

 

繼續沿著內核函數調用鏈,我們最終會來到load_elf_binary函數,該函數是整個系統調用的核心。

由于linux上執行的程序基本上都是elf格式,所以內核選擇的加載函數是load_elf_binary,看這個函數時,可以參考elf格式的man文檔:

https://man.archlinux.org/man/elf.5

該函數比較復雜,我對其做了大量刪減,并添加了很多注釋:

 

該函數最后會調用start_thread函數,進而會調用start_thread_common函數:

 

這個函數重點需要注意的是對regs->ip和regs->sp的賦值,其作用在load_elf_binary函數的截圖中已經注釋過了,就是在返回到用戶區之后,這兩個字段的值會被分別拷貝到rip和rsp寄存器里,所以這里的賦值,就相當于在返回用戶區之后,對rip和rsp寄存器的賦值,這個在 精致全景圖 | 系統調用是如何實現的 有講。

到這里內核部分的代碼就都已經結束了。

由load_elf_binary函數截圖中可見,regs->ip中設置的地址是elf_entry,即動態鏈接器的起始地址,而不是我們自己程序的起始地址。

原因是,我們還需要動態鏈接器繼續幫我們準備執行環境,比如幫我們加載程序依賴的動態鏈接庫等。

所以在execve系統調用返回到用戶區之后,代碼流程就進入到了動態鏈接器里的邏輯,即上面全景圖中的紫色區域:

 

上圖中的_start是動態鏈接器的起始執行地址,這個可以通過下面的方式來確認:

 

在_start函數中,先將rsp寄存器的值,即上面內核新初始化的堆棧的棧頂地址,賦值到rdi中,然后再使用call指令,調用_dl_start函數。

之所以要賦值到rdi寄存器中,是因為c語言的calling convention約定好的,用此方式來傳遞參數。

再看_dl_start函數:

 

該函數調用了_dl_start_final,返回一個地址,這個地址就是我們自己程序的起始地址。

再看_dl_start_final:

 

該函數又調用了_dl_sysdep_start:

 

在這里,動態鏈接器通過內核初始化的堆棧區中的auxiliary vector,找到最終用戶程序的起始執行地址。

再之后,動態鏈接器的函數調用鏈依次退出,最終返回到上面的_start函數。

_start函數之后會順序執行_dl_start_user,相關代碼也在上面的_start函數的截圖里。

其邏輯是,先將rax中的值,即_dl_start函數返回的最終用戶程序的起始地址,賦值到r12寄存器中,然后再jmp到r12寄存器指向的地址,即開始執行最終的用戶程序邏輯。

至于rax中的值,為什么是_dl_start函數返回的地址,這個其實也是 c calling convention 中的約定,感興趣可以自己查下。

以上就是動態鏈接器的全部邏輯,其對應于全景圖中的紫色部分。

最后,邏輯進入到了全景圖中的粉色部分。

動態鏈接器從內核設置的auxiliary vector中,獲取的用戶程序的起始地址,還并不是我們的main函數,而是glibc中一段名為_start的代碼,這個可以通過下面的方式確認:

 

該_start代碼段內容如下:

 

它從堆棧中獲取到argc和argv,然后調用__libc_start_main:

 

在__libc_start_main里,才真正的調用了我們寫的main函數。

當main函數返回之后,__libc_start_main里用main函數返回的值,作為該進程的退出碼,然后調用exit退出當前進程。

當該進程退出后,shell主進程也從waitpid的阻塞狀態返回,并攜帶用戶程序的退出碼。

在上面全景圖這個示例中,返回碼為99:

 

之后,shell主進程又進入到下一次循環,繼續等待用戶命令并執行,也就是說,又進入到全景圖中的藍色部分。

至此,在linux上執行程序的流程,就形成了一個完整閉環。

你,學廢了嗎?

本文轉載自微信公眾號「卯時卯刻」,可以通過以下二維碼關注。轉載本文請聯系卯時卯刻公眾號。

 

責任編輯:武曉燕 來源: 卯時卯刻
相關推薦

2024-09-30 10:09:52

2022-03-15 13:09:05

JavaScript編程語言代碼

2024-08-30 08:30:29

CPU操作系統寄存器

2021-04-15 18:09:14

存儲程序計算機

2025-06-27 09:32:47

GoRedis單線程

2021-02-19 08:11:39

Flink Function接口

2022-04-15 08:15:49

操作系統程序計算機

2023-03-02 23:09:53

Node.jsC++JS

2023-03-05 22:30:25

JavaCPU

2021-06-09 08:00:00

Python編程語言開發

2022-12-06 09:03:44

代碼fork系統

2011-11-25 14:19:49

dllexe木馬

2022-02-24 08:30:24

操作系統CPU程序

2023-09-22 23:00:11

Java虛擬機

2011-05-24 15:29:05

程序CC++

2019-07-18 14:31:54

區塊鏈公共區塊鏈區塊鏈技術

2025-07-08 02:55:00

2012-08-27 09:10:05

JVMJava

2021-03-15 08:33:01

CC++動態庫

2010-02-22 15:06:05

Python解釋程序
點贊
收藏

51CTO技術棧公眾號

精品99在线观看| 日本wwww色| 日本在线免费播放| 国内成人免费视频| 欧美国产视频日韩| 一区二区三区少妇| 国产精品蜜月aⅴ在线| 亚洲免费观看在线视频| 九九久久99| 91免费视频播放| 亚洲视频播放| 蜜臀久久99精品久久久无需会员 | 波多野结衣午夜| 亚洲澳门在线| 精品偷拍各种wc美女嘘嘘| 日本xxxx黄色| segui88久久综合9999| 国产精品五月天| 激情伦成人综合小说| 中文字幕日韩国产| 亚洲综合欧美| 欧美激情免费视频| 日本裸体美女视频| 欧美**字幕| 亚洲成人精品av| 激情图片中文字幕| 日本欧美一区| 欧美日韩在线免费| 免费人成自慰网站| 毛片在线播放a| 国产欧美一区二区三区鸳鸯浴| 99久久免费国| 国产视频一区二区三区四区五区| 日本美女一区二区三区视频| 国产69精品久久久久久| 国产一级片视频| 91精品国产乱码久久久久久 | 91在线高清免费观看| 欧美brazzers| 亚洲综合另类| 欧美专区福利在线| 99视频在线看| 影音先锋日韩资源| 欧美夫妻性生活视频| 日本成人精品视频| 久久看人人摘| 久久精彩免费视频| 天天爽天天爽天天爽| 国产一区二区三区四区大秀| 国产视频精品va久久久久久| avtt香蕉久久| 国产成人久久| 国产亚洲欧美视频| 99久久99久久精品免费| jvid福利在线一区二区| 亚洲天堂2020| 国产人妻大战黑人20p| 欧美男同视频网| 亚洲天堂av综合网| www.日本高清视频| 欧美艳星介绍134位艳星| 亚洲视频自拍偷拍| 粉嫩精品久久99综合一区| 日韩中文在线电影| 久久精品99国产精品酒店日本| 国产一二三av| 香蕉国产精品| 久久久久久久久网站| 久久精品视频久久| 亚洲制服少妇| 国产精品久久久久久久av电影| 中文字幕 视频一区| 久久99日本精品| 亚洲永久免费观看| 秋霞网一区二区| 久久在线观看免费| 午夜精品一区二区三区在线观看 | 欧美精品九九久久| 色网站在线播放| 视频一区欧美精品| 国产一区二区色| 亚洲成人一级片| 99久久综合国产精品| 欧美连裤袜在线视频| 在线观看免费网站黄| 亚洲精品精品亚洲| 1024av视频| 九九热这里有精品| 日韩一区二区三区免费看| 熟妇高潮一区二区| 第一社区sis001原创亚洲| 另类美女黄大片| 色网站在线播放| 精品一区二区三区在线观看国产 | 久久国产小视频| 久久99热精品这里久久精品| 国产成人精品网| 精品一区二区在线视频| 国产专区一区二区| 日本免费视频在线观看| 五月婷婷综合网| 深夜黄色小视频| 开心激情综合| 伦伦影院午夜日韩欧美限制| www.中文字幕在线观看| 精品一区二区三区免费| 精品国产福利| 黄色免费网站在线观看| 欧美色另类天堂2015| 黄色三级视频在线播放| 久久av超碰| 欧美黑人国产人伦爽爽爽| 久久人人爽人人爽人人片av免费| 丰满放荡岳乱妇91ww| 亚洲成人自拍视频| 欧美久久天堂| 日韩欧美中文一区| 青青青视频在线播放| av不卡免费看| 51国偷自产一区二区三区的来源 | 欧美国产精品人人做人人爱| 亚洲一级不卡视频| 成人www视频在线观看| 午夜小视频在线播放| 中文字幕在线一区| 看av免费毛片手机播放| 嫩呦国产一区二区三区av| 国产小视频国产精品| 日本五十熟hd丰满| 国产制服丝袜一区| 婷婷四月色综合| 小早川怜子影音先锋在线观看| 日韩欧美亚洲国产精品字幕久久久| 久久久久久久久久久久| 国产欧美日韩综合一区在线播放 | 亚洲精品中文字幕无码蜜桃| 福利欧美精品在线| 免费不卡欧美自拍视频| 11024精品一区二区三区日韩| 久久无码av三级| 青青草精品视频在线| 日韩不卡在线视频| 欧美成人精品在线| 国产又粗又黄又爽的视频| 国产精品三级电影| 亚洲欧美国产日韩综合| 日韩精品网站| 国产精品夜间视频香蕉| a视频网址在线观看| 在线观看国产日韩| 男人的天堂av网| 日韩电影一区二区三区四区| 欧美一区国产一区| 国产成人精选| 日韩中文字幕精品视频| 国产精品无码在线播放| 亚洲欧美视频在线观看| 亚洲五月激情网| 好看的日韩av电影| 国产专区一区二区| 电影亚洲精品噜噜在线观看| 亚洲日本aⅴ片在线观看香蕉| av片免费观看| 国产精品蜜臀av| 中文字幕在线观看日| 中文字幕日韩一区二区不卡 | 亚洲欧美一区二区久久| 日批视频在线看| 欧美日韩亚洲国产精品| 国产不卡一区二区在线观看| а√在线中文在线新版| 亚洲精品一区久久久久久| 久久国产香蕉视频| 亚洲欧洲av在线| 熟妇女人妻丰满少妇中文字幕| 欧美人成在线| 精品一区在线播放| 欧美va在线| 久久影视免费观看| 日韩一级片免费观看| 色婷婷狠狠综合| 国产老头老太做爰视频| 成人免费三级在线| caoporn超碰97| 欧美1区2区3区| 久久综合久久久| 日本精品在线一区| 欧美大码xxxx| 欧美日韩激情视频一区二区三区| 欧美色图第一页| 久久国产一级片| 国产亚洲精品bt天堂精选| 日韩视频在线观看一区二区三区| 伊人影院久久| 在线观看欧美亚洲| 美女一区二区在线观看| 国产一区红桃视频| 91美女主播在线视频| 色诱女教师一区二区三区| 成人毛片视频免费看| 色乱码一区二区三区88| 欧美黄色免费看| 久久影院视频免费| 不许穿内裤随时挨c调教h苏绵| 久久蜜桃精品| 久久精品xxx| 欧美高清视频在线观看mv| 国产另类自拍| 国产精品一区免费在线| 欧美综合一区第一页| 色呦呦在线视频| www亚洲精品| 飘雪影视在线观看免费观看| 日韩欧美国产一二三区| 中文字幕在线观看国产| 色综合久久久久网| 日韩 欧美 精品| 亚洲精品视频免费看| 国产一区二区三区四区在线| 91麻豆精品在线观看| 苍井空张开腿实干12次| 精品一区二区三区久久| www.99在线| 久久精品30| 777av视频| 一区在线播放| 老司机午夜网站| 97国产成人高清在线观看| 欧美人xxxxx| 欧美巨大xxxx| 国产日韩一区二区三区| av自拍一区| 成人一区二区在线| 日韩欧美高清一区二区三区| 成人国产精品av| 四虎永久精品在线| 国产美女精彩久久| 播放一区二区| 国产精品久久久久久久av大片| 午夜精品成人av| 日韩av免费一区| 向日葵视频成人app网址| 欧美中文在线观看| www.成人爱| 日韩av电影在线播放| 欧美片第1页| 日本久久久久久久久| 一区二区电影免费观看| 日韩免费精品视频| 蜜桃成人精品| 国产精品日韩欧美大师| 美女色狠狠久久| 国产乱肥老妇国产一区二| 亚洲人体在线| 91精品天堂| 超碰成人免费| 久久久久久国产精品免费免费| 琪琪久久久久日韩精品| 蜜桃网站成人| 日韩成人a**站| 女女同性女同一区二区三区按摩| 欧美不卡一区| 亚洲国产精品无码av| 国产日韩欧美高清免费| 妞干网在线免费视频| 日韩av一二三| 亚洲综合20p| 成人h版在线观看| 成人免费毛片日本片视频| 久久久国产精品不卡| 五月激情四射婷婷| 亚洲欧美韩国综合色| 亚洲一区二区91| 狠狠躁夜夜躁人人爽天天天天97| 一级黄色在线观看| 在线成人小视频| 欧美在线精品一区二区三区| 亚洲精品一区av在线播放| 日本三级在线视频| 欧美激情乱人伦| 校园春色亚洲色图| 成人精品一区二区三区电影免费| 中文字幕区一区二区三| 免费中文日韩| 中文在线日韩| 日韩无套无码精品| 国产在线麻豆精品观看| 黄色片视频免费观看| 国产精品久久精品日日| 国产真实夫妇交换视频| 91福利在线免费观看| 99久久免费国产精精品| 亚洲欧美中文字幕| av在线麻豆| 国产精品扒开腿爽爽爽视频| 欧美大片91| 日本不卡久久| 影音国产精品| 三区视频在线观看| 91免费版在线看| 69av.com| 欧美日韩精品一区二区三区四区| 亚洲精品久久久久久动漫器材一区| 亚洲欧美在线免费| 青春草在线视频| 国产精品美女在线| 美女主播精品视频一二三四| a级网站在线观看| 日韩专区一卡二卡| 中国一级特黄录像播放| 亚洲三级在线播放| 丰满人妻一区二区三区四区| 亚洲白虎美女被爆操| 免费高清在线观看| 青青草成人在线| 国产精品网在线观看| 美女在线免费视频| 美女爽到高潮91| 欧美做受高潮6| 高潮白浆女日韩av免费看| 国产高清精品软件丝瓜软件| 最近中文字幕2019免费| 欧美成人精品一区二区男人小说| 国产高清在线一区二区| 中文字幕免费一区二区| www.cao超碰| 国产精品少妇自拍| 在线免费观看av网址| 精品亚洲一区二区三区在线观看 | 污视频网站免费观看| 免费av一区二区| 精品一区二区三区中文字幕| 在线免费观看成人网| 理论片日本一区| 欧美日韩国产黄色| 欧美系列一区二区| 二区在线观看| 国产精品国产三级国产专播精品人 | 91色视频在线观看| 日韩在线精品| 日本中文字幕影院| 国产精品不卡在线观看| 中文字幕一区二区免费| 在线视频日韩精品| 91精品店在线| 亚洲欧美日韩另类精品一区二区三区| 日本特黄久久久高潮| 欧美a在线播放| 欧美精品一卡两卡| 午夜av在线免费观看| 成人欧美一区二区三区视频xxx| 欧美午夜一区| 国产精品久久无码| 欧美视频13p| 91免费在线| 91久热免费在线视频| 午夜精品久久| 国产二级一片内射视频播放| 懂色aⅴ精品一区二区三区蜜月| 日本电影一区二区在线观看| 国产v综合ⅴ日韩v欧美大片| 欧美日韩一二| 日韩欧美色视频| 五月天国产精品| 国产黄色在线| 91精品视频在线| 尤物网精品视频| 99久久人妻无码精品系列| 欧美日韩中文另类| 日本性爱视频在线观看| 国产精品伊人日日| 日韩影院精彩在线| 亚洲精品一区二区三区在线播放| 日韩欧美中文字幕精品| 国内精彩免费自拍视频在线观看网址 | 欧美三级电影在线| 女人另类性混交zo| 中文字幕中文字幕中文字幕亚洲无线| www.麻豆av| 热久久这里只有精品| 午夜久久免费观看| 欧美肉大捧一进一出免费视频| 在线精品视频免费观看| 宅男网站在线免费观看| 麻豆亚洲一区| 国产在线精品一区二区| 亚洲综合一二三| 久久久91精品国产| 天海翼精品一区二区三区| 九九热免费在线观看| 亚洲国产一区二区三区| 国产三级电影在线观看| 3d动漫精品啪啪一区二区三区免费 | 亚洲最大成人在线观看| 亚洲第一狼人社区| 日本在线免费播放| 欧美成人免费在线| 国产精品69毛片高清亚洲| 波多野结衣激情视频| 久久久久久久国产精品|