中文字幕第五页-中文字幕第页-中文字幕韩国-中文字幕最新-国产尤物二区三区在线观看-国产尤物福利视频一区二区

進程棧、線程棧、內核棧分別是什么

本篇內容主要講解“進程棧、線程棧、內核棧分別是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“進程棧、線程棧、內核棧分別是什么”吧!

創新互聯公司服務項目包括固陽網站建設、固陽網站制作、固陽網頁制作以及固陽網絡營銷策劃等。多年來,我們專注于互聯網行業,利用自身積累的技術優勢、行業經驗、深度合作伙伴關系等,向廣大中小型企業、政府機構等提供互聯網行業的解決方案,固陽網站推廣取得了明顯的社會效益與經濟效益。目前,我們服務的客戶以成都為中心已經輻射到固陽省份的部分城市,未來相信會繼續擴大服務區域并繼續獲得客戶的支持與信任!

進程描述符 task_struct

線程創建的時候,加上了 CLONE_VM 標記,這樣 線程的內存描述符 將直接指向 父進程的內存描述符。

內存描述符mm_struct

進程棧、線程棧、內核棧分別是什么

進程棧:stack

線程棧:使用mmap系統調用分配的空間,但是mmap分配的系統空間是什么呢?也就是上圖中的mmap區域或者說共享的內存映射區域是什么呢?它的方向是向上生長還是向下生長的?

mmap其實和堆一樣,實際上可以說他們都是動態內存分配,但是嚴格來說mmap區域并不屬于堆區,反而和堆區會爭用虛擬地址空間。

這里要提到一個很重要的概念,內存的延遲分配,只有在真正訪問一個地址的時候才建立這個地址的物理映射,這是Linux內存管理的基本思想。Linux內核在用戶申請內存的時候,只是給它分配了一個線性區(也就是虛擬內存),并沒有分配實際物理內存;只有當用戶使用這塊內存的時候,內核才會分配具體的物理頁面給用戶,這時候才占用寶貴的物理內存。內核釋放物理頁面是通過釋放先行區,找到其對應的物理頁面,將其全部釋放的過程。

進程棧、線程棧、內核棧分別是什么

struct mm_struct {
    struct vm_area_struct *mmap;           /* 內存區域鏈表 */
    struct rb_root mm_rb;                  /* VMA 形成的紅黑樹 */
    ...
    struct list_head mmlist;               /* 所有 mm_struct 形成的鏈表 */
    ...
    unsigned long total_vm;                /* 全部頁面數目 */
    unsigned long locked_vm;               /* 上鎖的頁面數據 */
    unsigned long pinned_vm;               /* Refcount permanently increased */
    unsigned long shared_vm;               /* 共享頁面數目 Shared pages (files) */
    unsigned long exec_vm;                 /* 可執行頁面數目 VM_EXEC & ~VM_WRITE */
    unsigned long stack_vm;                /* 棧區頁面數目 VM_GROWSUP/DOWN */
    unsigned long def_flags;
    unsigned long start_code, end_code, start_data, end_data;    /* 代碼段、數據段 起始地址和結束地址 */
    unsigned long start_brk, brk, start_stack;                   /* 棧區 的起始地址,堆區 起始地址和結束地址 */
    unsigned long arg_start, arg_end, env_start, env_end;        /* 命令行參數 和 環境變量的 起始地址和結束地址 */
    ...
    /* Architecture-specific MM context */
    mm_context_t context;                  /* 體系結構特殊數據 */

    /* Must use atomic bitops to access the bits */
    unsigned long flags;                   /* 狀態標志位 */
    ...
    /* Coredumping and NUMA and HugePage 相關結構體 */
};

為什么需要區分這些棧,其實都是設計上的問題。這里就我看到過的一些觀點進行匯總,供大家討論:

  1. 為什么需要單獨的進程內核棧?

    • 所有進程運行的時候,都可能通過系統調用陷入內核態繼續執行。假設第一個進程 A 陷入內核態執行的時候,需要等待讀取網卡的數據,主動調用 schedule() 讓出 CPU;此時調度器喚醒了另一個進程 B,碰巧進程 B 也需要系統調用進入內核態。那問題就來了,如果內核棧只有一個,那進程 B 進入內核態的時候產生的壓棧操作,必然會破壞掉進程 A 已有的內核棧數據;一但進程 A 的內核棧數據被破壞,很可能導致進程 A 的內核態無法正確返回到對應的用戶態了;

  2. 為什么需要單獨的線程棧?

    • 此時 A1 的棧指針 esp 如果為初始值 0x7ffc80000000,則線程 A1 一但出現函數調用,必然會破壞父進程 A 已入棧的數據。

    • 如果此時線程 A1 的棧指針和父進程最后更新的值一致,esp 為 0x7ffc8000FF00,那線程 A1 進行一些函數調用后,棧指針 esp 增加到 0x7ffc8000FFFF,然后線程 A1 休眠;調度器再次換成父進程 A 執行,那這個時候父進程的棧指針是應該為 0x7ffc8000FF00 還是 0x7ffc8000FFFF 呢?無論棧指針被設置到哪個值,都會有問題不是嗎?

    • Linux 調度程序中并沒有區分線程和進程,當調度程序需要喚醒”進程”的時候,必然需要恢復進程的上下文環境,也就是進程棧;但是線程和父進程完全共享一份地址空間,如果棧也用同一個那就會遇到以下問題。假如進程的棧指針初始值為 0x7ffc80000000;父進程 A 先執行,調用了一些函數后棧指針 esp 為 0x7ffc8000FF00,此時父進程主動休眠了;接著調度器喚醒子線程 A1: 

  3. 進程和線程是否共享一個內核棧?

    • No,線程和進程創建的時候都調用 dup_task_struct 來創建 task 相關結構體,而內核棧也是在此函數中 alloc_thread_info_node 出來的。因此雖然線程和進程共享一個地址空間 mm_struct,但是并不共享一個內核棧。

  4. 為什么需要單獨中斷棧?

    • 這個問題其實不對,ARM 架構就沒有獨立的中斷棧。

進程空間中堆和棧的區別:

空間大小:棧系統指定大小限制在8M(M 級別),棧是連續空間;堆沒有限定,是不連續存儲空間,靠鏈表鏈接。

分配方式:堆都是程序員代碼中動態分配和回收的,沒有回收會產生內存泄露;棧有2種分配方式:靜態分配和動態分配。靜態分配是編譯器完成的,比如局部變量的分配。動態分配由alloca函數進行分配,但是棧的動態分配和堆是不同的,他的動態分配是由編譯器進行釋放,無需我們手工實現。

分配效率:棧分配專門的寄存器存放棧的地址,壓棧出棧都有專門的指令執行;堆是通過調用庫函數

棧:在函數調用時,第一個進棧的是主函數中后的下一條指令(函數調用語句的下一條可執行語句)的地址,然后是函數的各個參數,在大多數的 C 編譯器中,參數是由右往左入棧的,然后是函數中的局部變量。注意靜態變量是不入棧的。
當本次函數調用結束后,局部變量先出棧,然后是參數,最后棧頂指針指向最開始存的地址,也就是主函數中的下一條指令,程序由該點繼續運行。
堆:一般是在堆的頭部用一個字節存放堆的大小。堆中的具體內容有程序員安排。

總之,棧比堆效率高,但沒有堆靈活,優先使用棧,大內存使用堆。

char a[] = "hello"; //字符數組a的容量是6個字符,其內容為hello。a的內容可以改變,如a[0]= ‘X’

char *p = "world";//指針p指向常量字符串“world”(位于靜態存儲區,內容為world),常量字符串的內容是不可以被修改的。

/**
*內核空間
*棧:grow down,大小系統設置~8M,連續空間,編譯器自動分配
*Memory Mapping Seg:堆棧共享,線程棧
*堆:grow up,大小硬件定,不連續空間,程序員malloc
*BSS:Block Started by Symbol,未初始化的全局變量和靜態變量(靜態data區)
*數據段:存放已初始化的全局變量、靜態變量(全局和局部)、const常量數據(常量data區)
*代碼段:存放CPU執行的機器指令,代碼區是可共享,并且是只讀的。這部分區域的大小在程序運行前就已經確定
**/

#include <string>
int a=0;    //數據段:全局初始化變量
char *p1;   //BSS:全局未初始化變量
void main()
{
    int b;//棧
    char s[] = "abc";   //棧
    char *p2;         //棧
    char *p3="123456";   //123456\0在常量區(代碼段??),p3在棧上。
    static int c=0;   //數據段:全局(靜態)初始化區
    *p1 = (char*)malloc(10);  //分配得來的10字節區域在堆上
    *p2 = (char*)malloc(20);  //分配得來的20字節區域在堆上。
    strcpy(p1,"123456");   //123456\0放在常量區,編譯器可能會將它與p3所向"123456\0"優化成一個地方。
}

//const 常量 或右值常量如"123456"放在數據段還是代碼段??

malloc與free是C++/C語言的標準庫函數,new/delete是C++的運算符。它們都可用于申請動態內存和釋放內存。但是new/delete會調用對象的構造和析構函數。

到此,相信大家對“進程棧、線程棧、內核棧分別是什么”有了更深的了解,不妨來實際操作一番吧!這里是創新互聯網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

當前標題:進程棧、線程棧、內核棧分別是什么
標題網址:http://www.2m8n56k.cn/article48/jphchp.html

成都網站建設公司_創新互聯,為您提供電子商務軟件開發App設計網站改版微信公眾號品牌網站制作

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:[email protected]。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

網站優化排名
主站蜘蛛池模板: 在线视频欧美亚洲 | 仑乱高清在线一级播放 | 91精品国产高清久久久久久91 | 日韩高清成人毛片不卡 | a级国产精品片在线观看 | 不卡精品国产_亚洲人成在线 | 日韩欧美在线播放 | 亚洲国产日韩欧美综合久久 | 亚洲毛片在线观看 | 岛国搬运工最新网地址 | 欧美成人亚洲欧美成人 | 国产精品九九 | 亚洲精品一区二区综合 | 欧美亚洲国产精品久久久久 | 亚洲精品综合欧美一区二区三区 | 一级毛片中文字幕 | 最近最新中文字幕免费的一页 | 免费又黄又爽视频 | 91精品日本久久久久久牛牛 | 最新亚洲人成网站在线影院 | 久久精品国产只有精品6 | 国产成人一区免费观看 | 成人午夜 | 亚洲综合亚洲 | 99久久99久久久99精品齐 | 色欧美hdvideosxs4k | 99精品国产免费久久国语 | 国产福利精品在线观看 | www.99在线 | 一级视频网站 | 亚州视频一区二区 | 亚洲精品久久久久久久无 | 免费的三级网站 | 美女视频黄a视频美女大全 美女视频黄a视频免费全程 | 日本阿v视频在线观看高清 日本波多野结衣视频 | 色屁屁一区二区三区视频国产 | 日韩黄色在线 | 国产日韩欧美一区二区三区在线 | 国内9l视频自拍 | 日本阿v精品视频在线观看 日本阿v视频在线观看高清 | 亚洲人成亚洲人成在线观看 |