• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            jake1036

            linux內核學習之八 內核體系結構

                                                                                                 linux內核體系結構
                   1 操作系統整體架構
                      分為四個部分: 用戶應用程序 , 操作系統服務部分 , 操作系統內核部分, 硬件系統部分。
                   2  linux內核模式
                       應用程序使用指定的參數值執行系統調用(int x80) ,使CPU從用戶態切換到核心態,然后操作系統根據具體的參數值調用特定的系統調用服務程序,
                       這些服務程序則根據需要再調用底層的一些支持函數以完成特定的功能。
                      在完成了應用程序所要求的服務程序之后,操作系統從核心態回到了用戶態,返回到應用程序中執行后面的指令。
                      

            3 內核體系結構
              內核體系結構主要由5部分組成 :
               (1) 進程調度 (2) 內存管理 (3) 進程間通信 (4) 文件系統 (5) 網絡接口
             





            下圖為 物理內存使用的功能分布圖 
                       

            內核模塊占用了 物理內存的最開始的位置,緊接著是 高速緩沖區 ,系統從外部讀取數據的時候,先把數據讀取到高速緩沖區中,然后再從高速緩沖區中
             將數據移動到主內存區中。

               4  內存地址的概念
                   存在以下三種不同的地址需要予以區別:
                   (1) 程序的虛擬地址 
                        是指由段選擇符和段內偏移地址兩個部分組成的地址。這兩部分組成的地址并沒有直接用來訪問內存地址,而是通過分段機制地址變化處理和映射之后,才能找到對應的物理內存中。虛擬地址空間由GDT映射的全局地址空間和LDT映射成的局部地址空間組成。 

                  (2) 線性地址 是虛擬地址到物理地址變換之間的中間層,是處理器可以尋址的內存空間中的地址。段中的偏移地址再加上相應段的基址,就生成了一個物理地址。

                  (3)物理地址 是指出現在CPU外部地址上的尋址內存的地址信號,是地址變換的最終結果地址。
             
               5 虛擬地址 線性地址 和 物理地址 之間的關系 
                 
                  5.1內核代碼和數據的地址
                       對于linux0.11內核來說,在head.s中已經把內核代碼段和數據段設置為長度為16MB的段,在線性地址空間中,這兩個段的范圍重疊,都是從線性地址空間0開始到地址0xFFFFFF共16MB地址范圍。      在該范圍中含有內核所有的代碼,內核段表(GDT , IDT , TSS) ,頁目錄表和內核的二級頁表,內核局部數據以及內核臨時堆棧。(該臨時堆棧將被用作第一個任務即任務0 的用戶堆棧) ,  所以內核代碼段和數據段在三種地址空間上的關系。
                                  


               通過上述分析得到 :
                    (1)內核代碼段和數據段區域 在線性地址空間和物理地址空間中是一樣的。
                    (2)GDT和IDT在內核數據段中,因此它們的線性地址空間也同樣等同于它們的物理地址地址。
                    (3) 除任務0以外,所有的其他任務所需要的物理內存頁面與線性地址中的不同或部分不同,因此內核 需要動態地在主內存區中為它們作映射操作,
                          動態地建立頁目錄項和頁表項。


                5.2任務0的地址對應關系
            任務0是系統中一個人工啟動的第一個任務,它的代碼段和數據段長度被設置為640kb ,該任務的代碼和數據直接包含在內核代碼和數據段中,是從線性地址0開始的640kb內容,因此它可以使用內核代碼已經設置好的頁目錄和頁表進行分頁地址變換。同樣它的代碼段和數據段在內存中也是重疊的。





             5.3  任務1的地址對應關系
                     任務1 也是一個特殊的任務。它的代碼也在內核代碼區域中。與任務0不同的是在線性地址空間中,系統在使用fork 創建任務時,為存放任務1 的二級頁表而在主內存區申請了一頁內存來存放,并復制了任務0 的頁目錄和二級頁表項。



             5.4其他任務的地址對應關系
                   
                 對于從任務2開始的進程來說,它們的父進程都是init進程(任務1) 。從任務2開始,如果任務號以nr來表示,那么任務nr在線性地址空間中的起始位置將是 nr * 64MB 。
                  

            5.4 用戶申請內存的動態分配
                  當用C函數庫中的malloc函數進行內存動態分配的時候,內核并不會插手管理,因為每個進程的擁有64MB的內存空間。但是內核會為進程使用的代碼和數據維護一個
            當前位置值brk ,這個值保存在每個進程的數據結構中。它指出了進程代碼和數據在進程地址空間中的末端位置,當malloc 函數為程序分配內存時,它會通過系統調用
            brk() 把程序要求新增加的空間長度通知內核,內核代碼可以根據malloc()函數所提供的信息來更新brk的值。但是此時并不會為新申請的空間映射物理內存頁面。只有當程序尋址到某個不存在對應的物理頁面的時候,內核才會進行物理內存頁面的映射操作。
             

            6  Linux 系統的中斷系統

                       CPU根據中斷號獲取中斷向量值,即對應中斷服務程序的入口地址值。為了讓CPU由中斷號查到對應的中斷向量,就需要在內存中建立一張查詢表。
                 即中斷向量表(32位模式下稱為中斷描述符表), 80x86支持256個中斷,對應每個中斷要安排一個中斷服務程序。對應一個中斷號,它的中斷服務程序的入口地址就在
                 保存在0x0000:N x 4 處。

                    對于Linux 系統,在剛開始啟動的時候,它會使用BIOS提供的顯示和磁盤讀取中斷功能。 在內核正常運行之前則會在setup.s程序中重新初始化8259A芯片在head.s程序中重新設置的一張中斷向量表。
                
             7 linux 系統調用
                  系統調用是linux內核與上層應用程序進行交互通信的唯一接口。
                  用戶通過直接或者間接地調用中斷int 0x80 ,并在eax寄存器中指定系統調用功能號,即可以使用內核資源,包括系統硬件資源。 
                 在Linux 內核中,每個系統調用都具有唯一的一個系統調用功能號。 這些功能號 實際上對應于 系統調用處理程序指針數組表 sys_call_table[] 中的項的索引值。 
                 
              7.1系統調用處理過程
                  當應用程序經過庫函數向內核發出一個中斷可調用int 0x80時 ,就可以執行一個系統調用。
                  其中寄存器eax中存儲著中斷調用號 ,而寄存器中攜帶的參數可以依次存放在ebx  , ecx , edx中。因此Linux 0.11中最多可以向內核中傳遞三個參數。


              8 Linux進程控制 
                  對于0.11來說,系統最多同時運行64個進程。處理第一個進程使用“手工”創建以外,其余的進程都是通過fork系統調用產生。內核使用進程標識號來標識進程。
                   進程由可執行的指令代碼 數據 和堆棧區組成。進程中的代碼和數據部分 分別對應一個執行文件中的代碼段、數據段。每個進程只能訪問自己的代碼,數據和堆棧。
                   linux 系統中一個進程可以在內核態或者是在用戶態下執行,并且分別使用各自獨立的內核態堆棧 和 用戶態堆棧。  用戶堆棧用于進程在用戶態下臨時保存調用函
            數的參數、局部變量等數據。內核堆棧則含有內核程序執行函數調用時的信息。

                 在linux內核中,進程通常叫做任務,而把運行在用戶空間的程序稱作 進程。
                 

               8.1   任務數據結構 
                         內核程序通過使用進程表對進程進行管理,每個進程在進程表中占有一項。 在Linux系統中,進程表項是一個task_struct 任務結構指針。或者叫做進程控制塊,
                   其中保存著控制和管理進程的所有信息。
                        
               8.2  進程初始化
                       系統進入保護模式之后,就開始執行系統初始化程序init/main.c 。該程序首先確定如何分配使用系統物理內存,然后調用內核各個部分的初始化函數,
                   分別對內存管理、中斷處理、塊設備和字符設備、進程管理以及硬盤和軟盤進行初始化處理。此后程序把自己“手工”移動到任務0中運行,并使用fork系統調用首先創建出進程1 。 在進程1中將繼續執行應用環境的初始化并執行shell登錄程序。而原進程則會在系統空閑的時候被調度執行,此時任務0 僅執行pause()系統調用,其中又回去執行調度函數。
              
              8.3 CPU允許低級別的代碼通過調用門或者中斷、陷阱門來調用和轉移到高級別的代碼中去。 但是 ,反之則不行。所以內核采用這種中斷返回指令iret來實現,
                    由高級別到低級別的跳轉。

              9 創建新進程
                 linux系統中創建新進程都是使用fork() 系統調用。所有的進程都是通過復制進程0而得到的,都是進程0的子進程。
                  隨后對復制的任務數據結構,進行修改。把當前進程設置為新進程的父進程,清除信號位圖,并復位新進程的各統計值。
                 接著根據當前進程設置任務狀態段(TSS)中各個寄存器的值。
                 
                 此后系統設置新任務的代碼和數據段基地址、限長、并復制當前進程內存分頁管理的頁表。此時,系統并不為新的進程分配實際的物理內存頁面,
                 而是讓它共享父進程的內存頁面。只有當父進程或新進程中任意的一個有寫內存的操作時,系統才會為執行寫操作的進程分配相關的獨自使用的內存頁面。
                 這種處理方式叫做 寫實復制技術。

                 創建一個新的進程和加載一個執行程序文件時兩個不同的概念。當創建子進程的時候,它完全復制了父進程的代碼和數據區,并會在其中執行子進程部分的代碼。
                    
                 9.1進程調度
                      調度程序可以看在所有處于運行狀態的進程之間分配CPU運行時間的管理代碼。
                      linux的進程是搶占式的,但是被搶占的進程仍然處于TASK_RUNNING 狀態,只是暫時沒有被CPU運行。進程的搶占發生在進程處于用戶態執行階段,
                      在內核態執行時是不能被搶占的。
                       
                 9.2 調度程序
                       schedule()函數首先掃描任務數組。通過比較每個就緒態(TASK_RUNNING)的運行時間遞減滴答計數counter 的值來 確定當前哪個進程運行的時間最少。
                       哪一個值越大,就表示運行時間還不長,于是就選擇該進程,并使用任務切換宏函數切換到該進程執行。
                        
                        如果沒有其他進程執行,系統就會選擇進程0運行,進程0會調用pause()函數把自己置位可中斷的睡眠狀態,并再次使用schedule()函數。只要系統空閑就
                       調用進程0運行。 
                      
                  9.3進程切換
                        每當選擇出一個新的可以運行的進程時,schedule()函數就會調用定義在include/asm/system.h中的switch_to()宏執行實際進程切換操作。該宏會把CPU的當前進程狀態
                        替換為新進程的狀態。.
             
                  9.4 終止進程
                        當一個進程結束了運行或在半途中終止了運行,那么內核就需要釋放該進程所占用的系統資源。這包括進程運行時打開的文件、申請的內存等。
                      









                       
                           








                    









                 




             

                    


                


              



























            posted on 2010-10-08 19:49 kahn 閱讀(1504) 評論(0)  編輯 收藏 引用

            国产精品免费久久| 蜜臀久久99精品久久久久久| 久久精品国产男包| 人人妻久久人人澡人人爽人人精品 | 久久久亚洲欧洲日产国码二区| 日韩乱码人妻无码中文字幕久久| 99国产精品久久| 久久久久久一区国产精品| 亚洲精品无码久久久影院相关影片| 久久国产精品一区二区| 欧美亚洲国产精品久久高清| 高清免费久久午夜精品| 久久久久人妻一区精品| 777米奇久久最新地址| 亚洲人成电影网站久久| 久久精品国产只有精品2020| 午夜天堂av天堂久久久| 亚洲欧美成人久久综合中文网| 久久精品黄AA片一区二区三区| 亚洲精品WWW久久久久久| 蜜桃麻豆www久久| 久久精品99久久香蕉国产色戒| 国产成人精品综合久久久久| 久久国产免费直播| 国产精品久久久久jk制服| 亚洲精品蜜桃久久久久久| 久久精品国产99久久久香蕉| 久久久久亚洲AV无码专区网站| 国产精品99久久99久久久| 久久精品一本到99热免费| 欧美777精品久久久久网| AV无码久久久久不卡网站下载 | 久久综合亚洲鲁鲁五月天| 色诱久久av| 一本综合久久国产二区| 亚洲精品久久久www| 久久精品极品盛宴观看| 久久香综合精品久久伊人| 粉嫩小泬无遮挡久久久久久| 狠狠88综合久久久久综合网| 精品久久久久久久久中文字幕|