當前位置:首頁 > 公眾號精選 > strongerHuang
[導(dǎo)讀]一文讓你初步了解進程描述符 task_struct。

關(guān)注+星標公眾,不錯過精彩內(nèi)容

作者 |?吳偉東

轉(zhuǎn)自 |?嵌入式Hacker


目的:

  • 初步了解進程描述符 task_struct。

目錄:

  1. Linux 的進程
  2. Linux 的進程描述符
  • task_struct
  • 內(nèi)核如何找到 task_struct
  • task_struct 的分配和初始化
  • 實驗:打印 task_struct / thread_info / kernel mode stack
  • 環(huán)境:

    • Linux-4.14 + ARMv7

    1. Linux 的進程

    進程的術(shù)語是 process,是 Linux 最基礎(chǔ)的抽象,另一個基礎(chǔ)抽象是文件。

    最簡單的理解,進程就是執(zhí)行中 (executing, 不等于running) 的程序。

    更準確一點的理解,進程包括執(zhí)行中的程序以及相關(guān)的資源 (包括cpu狀態(tài)、打開的文件、掛起的信號、tty、內(nèi)存地址空間等)。

    一種簡潔的說法:進程 = n*執(zhí)行流 + 資源,n>=1。


    Linux 進程的特點:

    • 通過系統(tǒng)調(diào)用 fork() 創(chuàng)建進程,fork() 會復(fù)制現(xiàn)有進程來創(chuàng)建一個全新的進程。

    • 內(nèi)核里,并不嚴格區(qū)分進程和線程。

    • 從內(nèi)核的角度看,調(diào)度單位是線程 (即執(zhí)行流)??梢园丫€程看做是進程里的一條執(zhí)行流,1個進程里可以有1個或者多個線程。

    • 內(nèi)核里,常把進程稱為 task 或者 thread,這樣描述更準確,因為許多進程就只有1條執(zhí)行流。

    • 內(nèi)核通過輕量級進程 (lightweight process) 來支持多線程。1個輕量級進程就對應(yīng)1個線程,輕量級進程之間可以共享打開的文件、地址空間等資源。

    2. Linux 的進程描述符

    2.1 task_struct

    內(nèi)核里,通過 task_struct 結(jié)構(gòu)體來描述一個進程,稱為進程描述符 (process descriptor),它保存著支撐一個進程正常運行的所有信息。

    每一個進程,即便是輕量級進程(即線程),都有1個 task_struct。

    sched.h?(include\linux)

    struct?task_struct?{
    ????struct?thread_info?thread_info;
    ????volatile?long?state;
    ????void?*stack;

    ????[...]
    ????struct?mm_struct?*mm;

    ????[...]
    ????pid_t?pid;

    ????[...]
    ????struct?task_struct?*parent;

    ????[...]
    ????char?comm[TASK_COMM_LEN];

    ????[...]
    ?struct?files_struct?*files;

    ?[...]
    ?struct?signal_struct?*signal;
    }

    這是一個龐大的結(jié)構(gòu)體,不僅有許多進程相關(guān)的基礎(chǔ)字段,還有許多指向其他數(shù)據(jù)結(jié)構(gòu)的指針。

    它包含的字段能完整地描述一個正在執(zhí)行的程序,包括 cpu 狀態(tài)、打開的文件、地址空間、掛起的信號、進程狀態(tài)等。

    點擊查看大圖

    作為初學(xué)者,先簡單地了解部分字段就好:

    • struct thread_info thread_info: 進程底層信息,平臺相關(guān),下面會詳細描述。

    • long state: 進程當前的狀態(tài),下面是幾個比較重要的進程狀態(tài)以及它們之間的轉(zhuǎn)換流程。

    點擊查看大圖
    • void *stack: 指向進程內(nèi)核棧,下面會解釋。

    • struct mm_struct *mm: 與進程地址空間相關(guān)的信息都保存在一個叫內(nèi)存描述符 (memory descriptor) 的結(jié)構(gòu)體 (mm_struct) 中。

    點擊查看大圖
    • pid_t pid: 進程標識符,本質(zhì)就是一個數(shù)字,是用戶空間引用進程的唯一標識。

    • struct task_struct *parent: 父進程的 task_struct。

    • char comm[TASK_COMM_LEN]: 進程的名稱。

    • struct files_struct *files: 打開的文件表。

    • struct signal_struct *signal: 信號處理相關(guān)。

    其他字段,等到有需要的時候再回過頭來學(xué)習。

    2.2 當發(fā)生系統(tǒng)調(diào)用或者進程切換時,內(nèi)核如何找到 task_struct ?

    對于 ARM 架構(gòu),答案是:通過內(nèi)核棧 (kernel mode stack)。

    為什么要有內(nèi)核棧?

    • 因為內(nèi)核是可重入的,在內(nèi)核中會有多條與不同進程相關(guān)聯(lián)的執(zhí)行路徑。因此不同的進程處于內(nèi)核態(tài)時,都需要有自己私有的進程內(nèi)核棧 (process kernel stack)。

    當進程從用戶態(tài)切換到內(nèi)核態(tài)時,所使用的棧會從用戶棧切換到內(nèi)核棧。

    • 至于是如何切換的,關(guān)鍵詞是系統(tǒng)調(diào)用,這不是本文關(guān)注的重點,先放一邊,學(xué)習內(nèi)核要懂得恰當?shù)臅r候忽略細節(jié)。

    當發(fā)生進程切換時,也會切換到目標進程的內(nèi)核棧。

    • 同上,關(guān)鍵詞是硬件上下文切換 (hardware context switch),忽略具體實現(xiàn)。

    無論何時,只要進程處于內(nèi)核態(tài),就會有內(nèi)核??梢允褂?,否則系統(tǒng)就離崩潰不遠了。

    ARM 架構(gòu)的內(nèi)核棧和 task_struct 的關(guān)系如下:

    點擊查看大圖

    內(nèi)核棧的長度是 THREAD_SIZE,對于 ARM 架構(gòu),一般是 2 個頁框的大小,即 8KB。

    內(nèi)核將一個較小的數(shù)據(jù)結(jié)構(gòu) thread_info 放在內(nèi)核棧的底部,它負責將內(nèi)核棧和 task_struct 串聯(lián)起來。thread_info 是平臺相關(guān)的,在 ARM 架構(gòu)中的定義如下:

    //?thread_info.h?(arch\arm\include\asm)

    struct?thread_info?{
    ?unsigned?long?flags;??/*?low?level?flags?*/
    ?int?preempt_count;?/*?0?=>?preemptable,?<0?=>?bug?*/
    ?mm_segment_t?addr_limit;?/*?address?limit?*/
    ?struct?task_struct?*task;??/*?main?task?structure?*/
    ????[...]
    ?struct?cpu_context_save?cpu_context;?/*?cpu?context?*/
    ?[...]
    };

    thread_info 保存了一個進程能被調(diào)度執(zhí)行的最底層信息(low level task data),例如struct cpu_context_save cpu_context 會在進程切換時用來保存/恢復(fù)寄存器上下文。

    內(nèi)核通過內(nèi)核棧的棧指針可以快速地拿到 thread_info:

    //?thread_info.h?(include\linux)

    static?inline?struct?thread_info?*current_thread_info(void)
    {
    ????//?current_stack_pointer?是當前進程內(nèi)核棧的棧指針
    ?return?(struct?thread_info?*)
    ??(current_stack_pointer?&?~(THREAD_SIZE?-?1));
    }

    然后通過 thread_info 找到 task_struct:

    //?current.h?(include\asm-generic)

    #define?current?(current_thread_info()->task)

    內(nèi)核里通過 current 宏可以獲得當前進程的 task_struct。

    2.3 task_struct 的分配和初始化

    當上層應(yīng)用使用 fork() 創(chuàng)建進程時,內(nèi)核會新建一個 task_struct。

    進程的創(chuàng)建是個復(fù)雜的工作,可以延伸出無數(shù)的細節(jié)。這里我們只是簡單地了解一下 task_struct 的分配和部分初始化的流程。

    fork() 在內(nèi)核里的核心流程

    點擊查看大圖

    dup_task_struct() 做了什么?

    點擊查看大圖

    至于設(shè)置內(nèi)核棧里做了什么,涉及到了進程的創(chuàng)建與切換,不在本文的關(guān)注范圍內(nèi),以后再研究了。

    3. 實驗:打印 task_struct / thread_info / kernel mode stack

    實驗?zāi)康模?/strong>

    • 梳理 task_struct / thread_info / kernel mode stack 的關(guān)系。

    實驗代碼:

    #include?
    #include?
    #include?

    static?void?print_task_info(struct?task_struct?*task)
    {
    ????printk(KERN_NOTICE?"%10s?%5d?task_struct?(%p)?/?stack(%p~%p)?/?thread_info->task?(%p)",
    ????????task->comm,?
    ????????task->pid,
    ????????task,
    ????????task->stack,
    ????????((unsigned?long?*)task->stack)?+?THREAD_SIZE,
    ????????task_thread_info(task)->task);
    }

    static?int?__init?task_init(void)
    {
    ????struct?task_struct?*task?=?current;

    ????printk(KERN_INFO?"task?module?init\n");

    ????print_task_info(task);
    ????do?{
    ????????task?=?task->parent;
    ????????print_task_info(task);
    ????}?while?(task->pid?!=?0);

    ????return?0;
    }
    module_init(task_init);

    static?void?__exit?task_exit(void)
    {
    ????printk(KERN_INFO?"task?module?exit\n?");
    }
    module_exit(task_exit);

    運行效果:

    task?module?init
    ????insmod??3123?task_struct?(edb42580)?/?stack(ed46c000~ed474000)?/?thread_info->task?(edb42580)
    ??????bash??2393?task_struct?(eda13e80)?/?stack(c9dda000~c9de2000)?/?thread_info->task?(eda13e80)
    ??????sshd??2255?task_struct?(ee5c9f40)?/?stack(c9d2e000~c9d36000)?/?thread_info->task?(ee5c9f40)
    ??????sshd???543?task_struct?(ef15f080)?/?stack(ee554000~ee55c000)?/?thread_info->task?(ef15f080)
    ???systemd?????1?task_struct?(ef058000)?/?stack(ef04c000~ef054000)?/?thread_info->task?(ef058000)

    在程序里,我們通過 task_struct 找到 stack,然后通過 stack 找到 thread_info,最后又通過 thread_info->task 找到 task_struct。

    4. 相關(guān)參考

    • Linux 內(nèi)核設(shè)計與實現(xiàn) / 第 3.1 章節(jié)

    • 深入理解 Linux 內(nèi)核 / 3

    • Linux 內(nèi)核深度解析 / 2.5.1

    • 深入Linux 內(nèi)核架構(gòu) / 2.3

    ------------?END?------------


    推薦閱讀:
    C語言預(yù)處理命令分類和工作原理
    淺談Makefile、Kconfig和.config文件
    FreeRTOS中相對延時和絕對延時的區(qū)別

    關(guān)注 微信公眾號『嵌入式專欄』,底部菜單查看更多內(nèi)容,回復(fù)“加群”按規(guī)則加入技術(shù)交流群。


    點擊“閱讀原文”查看更多分享,歡迎點分享、收藏、點贊、在看。

    免責聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

    本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
    換一批
    延伸閱讀

    9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

    關(guān)鍵字: 阿維塔 塞力斯 華為

    加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

    關(guān)鍵字: AWS AN BSP 數(shù)字化

    倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

    關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

    北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風險,如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

    關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

    8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

    關(guān)鍵字: 騰訊 編碼器 CPU

    8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

    關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

    8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

    關(guān)鍵字: 華為 12nm 手機 衛(wèi)星通信

    要點: 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

    關(guān)鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

    北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

    關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

    北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

    關(guān)鍵字: BSP 信息技術(shù)
    關(guān)閉
    關(guān)閉