在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

從進程啟動是怎么一步步到main函數的

strongerHuang ? 來源:strongerHuang ? 作者:軒轅之風 ? 2020-11-03 15:51 ? 次閱讀

首先先劃定一下這個問題的討論范圍:C/C++語言

這篇文章主要討論的是操作系統層面上對于進程、線程的創建初始化等行為,而像PythonJava等基于解釋器、虛擬機的語言,如何進入到main函數執行,這背后的路徑則更長(包含了解釋器和虛擬機內部的執行流程),以后有機會再討論。所以這里就重點關注C/C++這類native語言的main函數是如何進入的。

本文會兼顧敘述Linux和Windows兩個主要平臺上的詳細流程。

創建進程

第一步,創建進程。

在Linux上,我們要啟動一個新的進程,一般通過fork+exec系列函數來實現,前者將當前進程“分叉”出一個孿生子進程,后者負責替換這個子進程的執行文件,來執行子進程的新程序文件。

這里的fork、exec系列函數,是操作系統提供給應用程序的API函數,在其內部最終都會通過系統調用,進入操作系統內核,通過內核中的進程管理機制,來完成一個進程的創建。

操作系統內核將負責進程的創建,主要有下面幾個工作要做:

創建內核中用于描述進程的數據結構,在Linux上是task_struct

創建新進程的頁目錄、頁表,用于構建新進程的內存地址空間

在Linux內核中,由于歷史原因,Linux內核早期并沒有線程的概念,而是用任務:task_struct來描述一個程序的執行實例:進程。

在內核中,一個任務對應就是一個task_struct,也就是一個進程,內核的調度單元也是一個個的個task_struct。

后來,多線程的概念興起,Linux內核為了支持多線程技術,task_struct實際上表示的變成了一個線程,通過將多個task_struct合并為一組(通過該結構內部的組id字段)再來描述一個進程。因此,Linux上的線程,也稱為輕量級進程。

系統調用fork的一個重要使命就是要去創建新進程的task_struct結構,創建完成后,進程就擁有了調度單元。隨后將開始可以參與調度并有機會獲得執行。

加載可執行文件

通過fork成功創建進程后,此時的子進程和父進程相當于一個細胞進行了有絲分裂,兩個進程“幾乎”是一模一樣的。

而要想子進程執行新的程序,在子進程中還需要用到exec系列函數來實現對進程可執行程序的替換。

exec系列函數同樣是系統調用的封裝,通過調用它們,將進入內核sys_execve來執行真正的工作。

這個工作細節比較多,其中有一個重要的工作就是加載可執行文件到進程空間并對其進行分析,提取出可執行文件的入口地址。

我們使用C、C++等高級語言編寫的代碼,最終通過編譯器會編譯生成可執行文件,在Linux上,是ELF格式,在Windows上,稱之為PE文件。

無論是ELF文件還是PE文件,在各自的文件頭中,都記錄了這個可執行文件的指令入口地址,它指示了程序該從哪里開始執行。

這個入口指向哪里,是我們的main函數嗎?這里賣一個關子,先來解決在這之前的一個問題:進程創建后,是如何來到這個入口地址的?

不管在Windows還是Linux上,應用線程都會經常在用戶空間和內核空間來回穿梭,這可能出現在以下幾種情況發生時:

系統調用

中斷

異常

從內核返回時,線程是如何知道自己從哪里進來的,該回到應用空間的哪里去繼續執行呢?

答案是,在進入內核空間時,線程將自動保存上下文(其實就是一些寄存器的內容,比如指令寄存器EIP)到線程的堆棧上,記錄自己從哪里來的,等到從內核返回時,再從堆棧上加載這些信息,回到原來的地方繼續執行。

前面提到,子進程是通過sys_execve系統調用進入到內核中的,在后面完成可執行文件的分析后,拿到了ELF文件的入口地址,將會去修改原來保存在堆棧上的上下文信息,將EIP指向ELF文件的入口地址。這樣等sys_execve系統調用結束時,返回到用戶空間后,就能夠直接轉到新的程序入口開始執行代碼。

所以,一個非常重要的特點是:exec系列函數正常情況下是不會返回的,一旦進入,完成使命后,執行流程就會轉向新的可執行文件入口。

另外需要提一下的是,在Linux上,除了ELF文件,還支持一些其他格式的可執行文件,如MS-DOS、COFF

除了二進制的可執行文件,還支持shell腳本,這個情況下將會將腳本解釋器程序作為入口來啟動

從ELF入口到main函數

上面交代了,一個新的進程,是如何執行到可執行文件的入口地址的。

同時也留了一個問題,這個入口地址是什么?是我們的main函數嗎?

這里有一個簡單的C程序,運行起來后輸出經典的hello world:

#include intmain(){ printf("hello,world! "); return0; }

通過gcc編譯后,生成了一個ELF可執行文件,通過readelf指令,可以實現對ELF文件的分析,這里可以看到ELF文件的入口地址是0x400430:

隨后,我們通過反匯編神器,IDA打開分析這個文件,看一下位于0x400430入口的地方是什么函數?

可以看到,入口地方是一個叫做_start的函數,并不是我們的main函數。

在_start的結尾,調用了__libc_start_main函數,而這個函數,位于libc.so中。

你可能疑惑,這個函數是哪里冒出來的,我們的代碼中并沒有用到它呢?

其實,在進入main函數之前,還有一個重要的工作要做,這就是:C/C++運行時庫的初始化。上面的__libc_start_main就是在完成這一工作。

在通過GCC進行編譯時,編譯器將自動完成運行時庫的鏈接,將我們的main函數封裝起來,由它來調用。

glibc是開源的,我們可以在GitHub上找到這個項目的libc-start.c文件,一窺__libc_start_main的真面目,我們的main函數正是被它在調用。

完整流程

到這里,我們梳理了,從進程創建fork,到通過exec系列函數完成可執行文件的替換,再到執行流程進入到ELF文件的入口,再到我們的main函數的完整流程。

Windows上的一些區別

下面簡單介紹下Windows上這一流程的一些差異。

首先是創建進程的環節,Windows系統將fork+exec兩步合并了一步,通過CreateProcess系列函數一步到位,在其參數中指定子進程的可執行文件路徑。

不同于Linux上進程和線程的邊界模糊,在Windows操作系統上,內核是有明確的進程和線程概念定義,進程用EPROCESS結構表示,線程用ETHREAD結構表示。

所以在Windows上,進程相關的工作準備就緒后,還需要單獨創建一個參與內核調度的執行單元,也就是進程中的第一個線程:主線程。當然,這個工作也封裝在了CreateProcess系列函數中了。

新進程的主線程創建完成后,便開始參與系統調度了。主線程從哪里開始執行呢?內核在創建時就明確進行了指定:nt!KiThreadStartup,這是一個內核函數,線程啟動后就從這里開始執行。

線程從這里啟動后,再通過Windows的異步過程調用APC機制執行提前插入的APC,進而將執行流程引入應用層,去執行Windows進程應用程序的初始化工作,比如一些核心DLL文件的加載(Kernel32.dll、ntdll.dll)等等。

隨后,再次通過APC機制,再轉向去執行可執行文件的入口點。

這后面和Linux上的機制類似,同樣沒有直接到main函數,而是需要先進行C/C++運行時庫的初始化,這之后經過運行時函數的包裝,才最終來到我們的main函數。

下面是Windows上,從創建進程到我們的main函數的完整流程(高清大圖:https://bbs.pediy.com/upload/attach/201604/501306_qz5f5hi1n3107kt.png):

現在你清楚,從進程啟動是怎么一步步到你的main函數的了嗎?

責任編輯:xj

原文標題:從創建進程到進入main函數,發生了什么?

文章出處:【微信公眾號:strongerHuang】歡迎添加關注!文章轉載請注明出處。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • WINDOWS
    +關注

    關注

    4

    文章

    3600

    瀏覽量

    90780
  • C語言
    +關注

    關注

    180

    文章

    7628

    瀏覽量

    139959
  • 函數
    +關注

    關注

    3

    文章

    4365

    瀏覽量

    63959
  • main
    +關注

    關注

    0

    文章

    38

    瀏覽量

    6324

原文標題:從創建進程到進入main函數,發生了什么?

文章出處:【微信號:strongerHuang,微信公眾號:strongerHuang】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦
    熱點推薦

    小白學大模型:零實現 LLM語言模型

    ://github.com/FareedKhan-dev/train-llm-from-scratch本文將為你提供個簡單直接的方法,從下載數據生成文本,帶你一步步構建大院模型。
    的頭像 發表于 04-30 18:34 ?218次閱讀
    小白學大模型:<b class='flag-5'>從</b>零實現 LLM語言模型

    解鎖樹莓派集群:一步步打造你的超級計算陣列!

    樹莓派集群簡介樹莓派集群是由多臺聯網的樹莓派計算機組成的網絡,它們作為個統、協調的單元協同工作。通過連接多臺樹莓派,用戶可以創建個低成本的并行計算環境,能夠處理基礎模擬和網頁托
    的頭像 發表于 04-25 16:17 ?289次閱讀
    解鎖樹莓派集群:<b class='flag-5'>一步步</b>打造你的超級計算陣列!

    CoT 數據集如何讓大模型學會一步一步思考?

    目前,大模型的回答路徑基本遵循 input-output 的方式,在面對復雜任務時表現不佳。反之,人類會遵循套有條理的思維流程,逐步推理得出正確答案。這種差異促使人們深入思考:如何才能讓大模型“智能涌現”,學會像人類樣“一步
    的頭像 發表于 04-24 16:51 ?169次閱讀
    CoT 數據集如何讓大模型學會<b class='flag-5'>一步</b><b class='flag-5'>一步</b>思考?

    【迅為電子】一步步教你完成iTOP-RK3568 EDP屏幕適配

    【迅為電子】一步步教你完成iTOP-RK3568 EDP屏幕適配
    的頭像 發表于 04-23 15:08 ?628次閱讀
    【迅為電子】<b class='flag-5'>一步步</b>教你完成iTOP-RK3568 EDP屏幕適配

    ST EDGE AI云服務最后一步無法下載工程是怎么回事?

    ST EDGE AI云服務我選擇使用ST提供的模型,使用cube ai 9.0.0,選擇STM32板卡。之后就按照文檔一步一步操作,基準測試也能運行的結果(說明云端是生成工程并編譯下載到開發板中
    發表于 03-13 08:17

    ADS1115在配置和轉換時的具體操作步驟,每一步的寄存器配置是怎樣的?

    ADS1115在配置和轉換時的具體操作步驟,每一步的寄存器配置是怎樣的???希望能給出配置和讀取數據的模塊函數
    發表于 02-12 08:25

    如果需要將DDC112U設置為非連續模式工作,應該如何一步一步正確地設置芯片?

    或狀態8,如果沒有CONV的切換發生,是否會直停留在上電時的這個狀態?如果需要將DDC112U設置為非連續模式工作,應該如何一步一步正確地設置芯片?
    發表于 01-09 07:43

    沙子變芯片,一步步帶你走進高科技的微觀世界

    在科技飛速發展的今天,芯片作為現代科技的核心元器件,其制造過程復雜且充滿挑戰。芯片不僅推動了信息技術、人工智能、物聯網等領域的進步,還成為衡量個國家科技實力的重要指標。然而,芯片制造并非易事,沙子芯片的每
    的頭像 發表于 12-19 10:44 ?629次閱讀
    沙子變芯片,<b class='flag-5'>一步步</b>帶你走進高科技的微觀世界

    FaceTime成詐騙“幫兇”,蘋果是怎么一步步丟掉“安全”光環的?

    蘋果想要在AI時代,重新給自己貼上“安全”的標簽,恐怕還學學安卓和鴻蒙。
    的頭像 發表于 11-03 17:39 ?3216次閱讀
    FaceTime成詐騙“幫兇”,蘋果是怎么<b class='flag-5'>一步步</b>丟掉“安全”光環的?

    TPA3128D2第3管腳輸出保護是什么原因導致的?

    TPA3128D2按照數據手冊第24頁圖36配置為MASTER模式,GAIN=26db,按典型應用的電路圖畫的電路板,上電后第3管腳輸出低電平,請問 1.應該怎樣一步步排除此故障? 2.是否按數據手冊第18頁中圖29的時序啟動芯片才能工作?
    發表于 10-22 06:17

    通過展頻進一步優化EMI

    電子發燒友網站提供《通過展頻進一步優化EMI.pdf》資料免費下載
    發表于 09-04 09:32 ?1次下載
    通過展頻進<b class='flag-5'>一步</b>優化EMI

    用XDS200仿真PGA900時候,單步執行程序PC支持并沒有按照C語言一步一步執行,為什么?

    我在用XDS200仿真PGA900時候,程序能正常引導main,單步執行程序, PC支持并沒有按照C語言一步一步執行, 這是什么原因? 以下是工程圖
    發表于 08-15 07:18

    昂科芯片燒錄高質量出海 唱響越南一步步新技術研討會

    8月8日,迎來了場科技盛事-2024越南一步步新技術研討會在河內·美利亞酒店隆重舉行。作為芯片燒錄領域的領導者,昂科技術應邀參會,吸引了眾多國內外業界專家和企業的關注。
    的頭像 發表于 08-10 09:20 ?1038次閱讀

    labview按名稱解綁簇報錯

    這是我在網上按照視頻一步步做的,請各位大神幫我看看,我打框的地方哪里錯了呀??為什么視頻老師做的就不報錯,我做的樣就錯了?
    發表于 07-14 12:06

    使用PCIe EtherCAT通訊卡控制IO站step by step(

    EtherCAT是種高效且常用的工業通訊協議。本系列文章將帶領您使用ZLG致遠電子的PCIeEtherCAT通訊卡,一步步實現從搭建編譯環境程序運行。ZLG致遠電子PCIeEtherCAT通訊卡
    的頭像 發表于 05-21 08:24 ?976次閱讀
    使用PCIe EtherCAT通訊卡控制IO<b class='flag-5'>從</b>站step by step(<b class='flag-5'>一</b>)
    主站蜘蛛池模板: 国产成人精品1024在线 | 日本69sex护士hd | 天天干天天操天天操 | 韩国三级中文 | 国内精品久久久久影院男同志 | 国产黄mmd在线观看免费 | 午夜久久免影院欧洲 | 亚洲免费二区三区 | 一级毛片在线免费视频 | 亚洲国产成人精品不卡青青草原 | 五月天婷婷综合网 | 色狠狠色综合久久8狠狠色 色狠狠网 | 色爱区综合激情五月综合激情 | 日日噜噜噜夜夜爽爽狠狠图片 | 欧美国产在线一区 | 欧美.亚洲.日本一区二区三区 | 天堂综合 | 一级特黄性色生活片一区二区 | 国产一区二区高清在线 | 国产免费高清视频在线观看不卡 | 午夜欧美精品久久久久久久 | 操吧 | 久久99热久久精品99 | 88av在线视频 | 国内一级特黄女人精品毛片 | 如果我们是季节韩剧在线观看 | 国产叼嘿网站免费观看不用充会员 | 一级片一级片一级片 | 四虎www成人影院免费观看 | 泰剧天堂 | 国产精品视频第一区二区三区 | 手机在线看 | 黄色视奸 | 日本高清免费一本视频在线观看 | 国产毛片毛片精品天天看 | 国产人免费人成免费视频 | 久青草视频在线 | 天天干夜夜看 | 中文字幕第五页 | 国产免费卡1卡2卡 | 一区二区美女视频 |