導航:首頁 > 數據分析 > 內核數據段區分是哪個進程的嗎

內核數據段區分是哪個進程的嗎

發布時間:2022-09-02 01:51:39

1. 內核線程和內核級線程有什麼區別

linux下線程分為用戶級線程和內核級線程,在內核來看,線程和進程是一樣的,本質上沒有區別內核提供的是創建進程的介面do_fork()。內核提供了兩個系統調用clone()和fork(),最終都用不同的參數調用do_fork()核內API。當然,要想實現線程,沒有核心對多進程(其實是輕量級進程)共享數據段的支持是不行的,因此,do_fork()提供了很多參數,包括CLONE_VM(共享內存空間)、CLONE_FS(共享文件系統信息)、CLONE_FILES(共享文件描述符表)、CLONE_SIGHAND(共享信號句柄表)和CLONE_PID(共享進程ID,僅對核內進程,即0號進程有效)。當使用fork系統調用時,內核調用do_fork()不使用任何共享屬性,進程擁有獨立的運行環境,而使用pthread_create()來創建線程時,則最終設置了所有這些屬性來調用__clone(),而這些參數又全部傳給核內的do_fork(),從而創建的「進程」擁有共享的運行環境,只有棧是獨立的,由__clone()傳入。具體可以參考>第三版,講的非常詳細

2. Linux 0.11版內核內存問題

我上網上查了點資料不知道有用不
以win32程序為例。
程序執行時,操作系統將exe文件映射入內存。exe文件格式為頭數據和各段數據組成。頭數據說明了exe文件的屬性和執行環境,段數據又分為數據段,代碼段,資源段等,段的多少和位置由頭數據說明。也就是說,不僅僅只是代碼段和數據段。這些段由不同的編譯環境和編譯參數控制,由編譯器自動生成exe的段和文件格式。當操作系統執行exe時,會動態建立堆棧段,它是動態的,並且屬於操作系統執行環境。

也就是說,程序在內存的映射一個為exe文件映射,包括數據段、代碼段等它是不變的。
另一個為堆棧段,它是隨程序運行動態改變的。

其他操作系統會有他自己的執行方式,但大體如上。

http://www.17lamp.net/forum/lamp/20081028122208
http://blog.csdn.net/lijingze2003/archive/2005/04/09/340804.aspx

3. 什麼是計算機線程進程和線程兩者有什麼區別

進程:

對應用程序來說,進程就像一個大容器。在應用程序被運行後,就相當於將應用程序裝進容器里了,你可以往容器里加其他東西(如:應用程序在運行時所需的變數數據、需要引用的DLL文件等),當應用程序被運行兩次時,容器里的東西並不會被倒掉,系統會找一個新的進程容器來容納它。

進程是由進程式控制制塊、程序段、數據段三部分組成。一個進程可以包含若干線程(Thread),線程可以幫助應用程序同時做幾件事(比如一個線程向磁碟寫入文件,另一個則接收用戶的按鍵操作並及時做出反應,互相不幹擾),在程序被運行後中,系統首先要做的就是為該程序進程建立一個默認線程,然後程序可以根據需要自行添加或刪除相關的線程。
是可並發執行的程序。在一個數據集合上的運行過程,是系統進行資源分配和調度的一個獨立單位,也是稱活動、路徑或任務,它有兩方面性質:活動性、並發性。進程可以劃分為運行、阻塞、就緒三種狀態,並隨一定條件而相互轉化:就緒--運行,運行--阻塞,阻塞--就緒。

進程為應用程序的運行實例,是應用程序的一次動態執行。看似高深,我們可以簡單地理解為:它是操作系統當前運行的執行程序。在系統當前運行的執行程序里包括:系統管理計算機個體和完成各種操作所必需的程序;用戶開啟、執行的額外程序,當然也包括用戶不知道,而自動運行的非法程序(它們就有可能是病毒程序)。
危害較大的可執行病毒同樣以「進程」形式出現在系統內部(一些病毒可能並不被進程列表顯示,如「宏病毒」),那麼及時查看並准確殺掉非法進程對於手工殺毒有起著關鍵性的作用。

進程是程序在計算機上的一次執行活動。當你運行一個程序,你就啟動了一個進程。顯然,程序是

死的(靜態的),進程是活的(動態的)。進程可以分為系統進程和用戶進程。凡是用於完成操作系統的各種

功能的進程就是系統進程,它們就是處於運行狀態下的操作系統本身;用戶進程就是所有由你啟動的進程。進程是操作系統進行資源分配的單位。

在Windows下,進程又被細化為線程,也就是一個進程下有多個能獨立運行的更小的單位。
1.進程的引入:
多道程序在執行時,需要共享系統資源,從而導致各程序在執行過程中出現相互制約的關系,程序的執行表現出間斷性的特徵。這些特徵都是在程序的執行過程中發生的,是動態的過程,而傳統的程序本身是一組指令的集合,是一個靜態的概念,無法描述程序在內存中的執行情況,即我們無法從程序的字面上看出它何時執行,何時停頓,也無法看出它與其它執行程序的關系,因此,程序這個靜態概念已不能如實反映程序並發執行過程的特徵。為了深刻描述程序動態執行過程的性質,人們引入「進程(Process)」概念。
2.進程的概念:
進程的概念是60年代初首先由麻省理工學院的MULTICS系統和IBM公司的CTSS/360系統引入的。
進程是一個具有獨立功能的程序關於某個數據集合的一次運行活動。它可以申請和擁有系統資源,是一個動態的概念,是一個活動的實體。它不只是程序的代碼,還包括當前的活動,通過程序計數器的值和處理寄存器的內容來表示。
進程是操作系統中最基本、重要的概念。是多道程序系統出現後,為了刻畫系統內部出現的動態情況,描述系統內部各道程序的活動規律引進的一個概念,所有多道程序設計操作系統都建立在進程的基礎上。
操作系統引入進程的概念的原因:
從理論角度看,是對正在運行的程序過程的抽象;
從實現角度看,是一種數據結構,目的在於清晰地刻劃動態系統的內在規律,有效管理和調度進入計算機系統主存儲器運行的程序。
3.進程的特徵
動態性:進程的實質是程序的一次執行過程,進程是動態產生,動態消亡的。
並發性:任何進程都可以同其他進程一起並發執行
獨立性:進程是一個能獨立運行的基本單位,同時也是系統分配資源和調度的獨立單位;
非同步性:由於進程間的相互制約,使進程具有執行的間斷性,即進程按各自獨立的、不可預知的速度向前推進
結構特徵:進程由程序、數據和進程式控制制塊三部分組成。
4.進程與程序的關系
程序是指令的有序集合,其本身沒有任何運行的含義,是一個靜態的概念。而進程是程序在處理機上的一次執行過程,它是一個動態的概念。
程序可以作為一種軟體資料長期存在,而進程是有一定生命期的。程序是永久的,進程是暫時的。
進程更能真實地描述並發,而程序不能;進程是由程序和數據兩部分組成的。
進程具有創建其他進程的功能,而程序沒有。
同一程序同時運行於若干個數據集合上,它將屬於若干個不同的進程。也就是說同一程序可以對應多個進程。
在傳統的操作系統中,程序並不能獨立運行,作為資源分配和獨立運行的基本單元都是進程。

Windows XP 常見的進程列表
[編輯本段]

1、最基本的系統進程
這些進程是系統運行的基本條件,有了這些進程,系統才能正常運行。

smss.exe Session Manager
csrss.exe 子系統伺服器進程
winlogon.exe 管理用戶登錄
services.exe 包含很多系統服務
lsass.exe
管理IP安全策略以及啟動ISAKMP/Oakley(IKE)和IP安全驅動程序。(系統服務)
產生會話密鑰以及授予用於互動式客戶/伺服器驗證的服務憑據(ticket)。(系統服務)
svchost.exe 包含很多系統服務
SPOOLSV.EXE 將文件載入到內存中以便遲後列印。(系統服務)
explorer.exe 資源管理器
internat.exe 托盤區的拼音圖標

2、附加的系統進程
這些進程不是必要的,你可以根據需要通過服務管理器來增加或減少
mstask.exe 允許程序在指定時間運行。(系統服務)
regsvc.exe 允許遠程注冊表操作。(系統服務)
winmgmt.exe 提供系統管理信息(系統服務)。
inetinfo.exe
通過 Internet 信息服務的管理單元提供 FTP 連接和管理。(系統服務)
tlntsvr.exe
允許遠程用戶登錄到系統並且使用命令行運行控制台程序。(系統服務)
允許通過Internet信息服務的管理單元管理 Web 和 FTP 服務。(系統服務)

tftpd.exe
實現TFTP Internet標准。該標准不要求用戶名和密碼。遠程安裝服務
的一部分。(系統服務)
termsrv.exe
提供多會話環境允許客戶端設備訪問虛擬的Windows 2000 Professional 桌面會話以及運行在伺服器上的基於Windows的程序。(系統服務)
dns.exe 應答對域名系統(DNS)名稱的查詢和更新請求。(系統服務)

3、不常用服務
以下服務很少會用到,上面的服務都對安全有害,如果不是必要的應該關掉
tcpsvcs.exe 提供在PXE可遠程啟動客戶計算機上遠程安裝 Windows 2000
Professional 的能力。(系統服務)
支持以下 TCP/IP 服務Character Generator,Daytime,Discard,Echo,以及Quote of the Day。(系統服務)
ismserv.exe
允許在Windows Advanced Server站點間發送和接收消息。(系統服務)
ups.exe
管理連接到計算機的不間斷電源(UPS)。(系統服務)
wins.exe
為注冊和解析NetBIOS型名稱的TCP/IP客戶提供NetBIOS名稱服務。(系統服務)
llssrv.exe License Logging Service(system service)
ntfrs.exe 在多個伺服器間維護文件目錄內容的文件同步。(系統服務)
RsSub.exe 控制用來遠程儲存數據的媒體。(系統服務)
locator.exe 管理 RPC 名稱服務資料庫。(系統服務)
lserver.exe 注冊客戶端許可證。(系統服務)
dfssvc.exe 管理分布於區域網或廣域網的邏輯卷。(系統服務)
clipsrv.exe
支持「剪貼簿查看器」,以便可以從遠程剪貼簿查閱剪貼頁面。(系統服務)
msdtc.exe
並列事務,是分布於兩個以上的資料庫,消息隊列,文件系統,或其它事務保護資源管理器。(系統服務)
faxsvc.exe 幫助您發送和接收傳真。(系統服務)
cisvc.exe Indexing Service(system service)
dmadmin.exe 磁碟管理請求的系統管理服務。(系統服務)
mnmsrvc.exe
允許有許可權的用戶使用NetMeeting遠程訪問Windows桌面。(系統服務)
netdde.exe
提供動態數據交換(DDE)的網路傳輸和安全特性。(系統服務)
smlogsvc.exe 配置性能日誌和警報。(系統服務)
rsvp.exe
為依賴質量服務(QoS)的程序和控制應用程序提供網路信號和本地通信控制
安裝功能。(系統服務)
RsEng.exe
協調用來儲存不常用數據的服務和管理工具。(系統服務)
RsFsa.exe 管理遠程儲存的文件的操作。(系統服務)
grovel.exe
掃描零備份存儲(SIS)卷上的重復文件,並且將重復文件指向一個數據存
儲點,以節省磁碟空間。(系統服務)
SCardSvr.exe
對插入在計算機智能卡閱讀器中的智能卡進行管理和訪問控制。(系統服務)
snmp.exe
包含代理程序可以監視網路設備的活動並且向網路控制台工作站匯報。(系
統服務)
snmptrap.exe
接收由本地或遠程SNMP代理程序產生的陷阱消息,然後將消息傳遞到運行在這台計算機上SNMP管理程序。(系統服務)
UtilMan.exe 從一個窗口中啟動和配置輔助工具。(系統服務)
msiexec.exe
依據.MSI文件中包含的命令來安裝、修復以及刪除軟體。(系統服務)

線程:
線程
開放分類: 編程、CPU、計算機軟體

是進程中的一個實體,是被系統獨立調度和分派的基本單位,線程自己不擁有系統資源,只擁有一點在運行中必不可少的資源,但它可與同屬一個進程的其它線程共享進程所擁有的全部資源。一個線程可以創建和撤消另一個線程,同一進程中的多個線程之間可以並發執行。由於線程之間的相互制約,致使線程在運行中呈現出間斷性。線程也有就緒、阻塞和運行三種基本狀態。
線程是程序中一個單一的順序控制流程.在單個程序中同時運行多個線程完成不同的工作,稱為多線程.
線程和進程的區別在於,子進程和父進程有不同的代碼和數據空間,而多個線程則共享數據空間,每個線程有自己的執行堆棧和程序計數器為其執行上下文.多線程主要是為了節約CPU時間,發揮利用,根據具體情況而定. 線程的運行中需要使用計算機的內存資源和CPU
線程的周期
新建 就緒 運行 阻塞 死亡
線程調度與優先順序
有線程進入了就緒狀態,需要有線程調度程序來決定何時執行,根據優先順序來調度.
線程組
每個線程都是一個線程組的一個成員,線程組把多個線程集成一個對象,通過線程組可以同時對其中的多個線程進行操作.在生成線程時必須將線程放在指定的線程組,也可以放在預設的線程組中,預設的就是生成該線程的線程所在的線程組.一旦一個線程加入了某個線程組,不能被移出這個組.
守護線程
是特殊的線程,一般用於在後台為其他線程提供服務.

4. Linux進程內存如何管理

Linux內存管理
摘要:本章首先以應用程序開發者的角度審視Linux的進程內存管理,在此基礎上逐步深入到內核中討論系統物理內存管理和內核內存的使用方法。力求從外到內、水到渠成地引導網友分析Linux的內存管理與使用。在本章最後,我們給出一個內存映射的實例,幫助網友們理解內核內存管理與用戶內存管理之間的關系,希望大家最終能駕馭Linux內存管理。
前言
內存管理一向是所有操作系統書籍不惜筆墨重點討論的內容,無論市面上或是網上都充斥著大量涉及內存管理的教材和資料。因此,我們這里所要寫的Linux內存管理採取避重就輕的策略,從理論層面就不去班門弄斧,貽笑大方了。我們最想做的和可能做到的是從開發者的角度談談對內存管理的理解,最終目的是把我們在內核開發中使用內存的經驗和對Linux內存管理的認識與大家共享。
當然,這其中我們也會涉及到一些諸如段頁等內存管理的基本理論,但我們的目的不是為了強調理論,而是為了指導理解開發中的實踐,所以僅僅點到為止,不做深究。
遵循「理論來源於實踐」的「教條」,我們先不必一下子就鑽入內核里去看系統內存到底是如何管理,那樣往往會讓你陷入似懂非懂的窘境(我當年就犯了這個錯誤!)。所以最好的方式是先從外部(用戶編程范疇)來觀察進程如何使用內存,等到大家對內存的使用有了較直觀的認識後,再深入到內核中去學習內存如何被管理等理論知識。最後再通過一個實例編程將所講內容融會貫通。
進程與內存
進程如何使用內存?
毫無疑問,所有進程(執行的程序)都必須佔用一定數量的內存,它或是用來存放從磁碟載入的程序代碼,或是存放取自用戶輸入的數據等等。不過進程對這些內存的管理方式因內存用途不一而不盡相同,有些內存是事先靜態分配和統一回收的,而有些卻是按需要動態分配和回收的。
對任何一個普通進程來講,它都會涉及到5種不同的數據段。稍有編程知識的朋友都能想到這幾個數據段中包含有「程序代碼段」、「程序數據段」、「程序堆棧段」等。不錯,這幾種數據段都在其中,但除了以上幾種數據段之外,進程還另外包含兩種數據段。下面我們來簡單歸納一下進程對應的內存空間中所包含的5種不同的數據區。
*代碼段*:代碼段是用來存放可執行文件的操作指令,也就是說是它是可執行程序在內存中的鏡像。代碼段需要防止在運行時被非法修改,所以只准許讀取操作,而不允許寫入(修改)操作——它是不可寫的。
*數據段*:數據段用來存放可執行文件中已初始化全局變數,換句話說就是存放程序靜態分配[1]的變數和全局變數。
BSS*段<a href="https://link.segmentfault.com/?enc=DcwhqnvkYMxrvWKNSDlpjw%3D%3D.%2BTVdR37FrzpDlx30Od%2F227j%2FFcDXfhqFymFBWKvF4UA%3D%3D">*[2]**:BSS段包含了程序中未初始化的全局變數,在內存中 bss段全部置零。
堆(heap*)*:堆是用於存放進程運行中被動態分配的內存段,它的大小並不固定,可動態擴張或縮減。當進程調用malloc等函數分配內存時,新分配的內存就被動態添加到堆上(堆被擴張);當利用free等函數釋放內存時,被釋放的內存從堆中被剔除(堆被縮減)
*棧*:棧是用戶存放程序臨時創建的局部變數,也就是說我們函數括弧「{}」中定義的變數(但不包括static聲明的變數,static意味著在數據段中存放變數)。除此以外,在函數被調用時,其參數也會被壓入發起調用的進程棧中,並且待到調用結束後,函數的返回值也會被存放回棧中。由於棧的先進先出特點,所以棧特別方便用來保存/恢復調用現場。從這個意義上講,我們可以把堆棧看成一個寄存、交換臨時數據的內存區。
進程如何組織這些區域?
上述幾種內存區域中數據段、BSS和堆通常是被連續存儲的——內存位置上是連續的,而代碼段和棧往往會被獨立存放。有趣的是,堆和棧兩個區域關系很「曖昧」,他們一個向下「長」(i386體系結構中棧向下、堆向上),一個向上「長」,相對而生。但你不必擔心他們會碰頭,因為他們之間間隔很大(到底大到多少,你可以從下面的例子程序計算一下),絕少有機會能碰到一起。

5. linux:進程

處理器的狀態和內核的數據不屬於進程,其他你所列舉的都是進程的內容,還有代碼段,堆棧段,許可權,優先順序等等,內容很多。

6. linux中使用了什麼內存管理方法,為什麼

「事實勝於雄辯」,我們用一個小例子(原形取自《User-Level Memory Management》)來展示上面所講的各種內存區的差別與位置。

進程的地址空間對應的描述結構是「內存描述符結構」,它表示進程的全部地址空間,——包含了和進程地址空間有關的全部信息,其中當然包含進程的內存區域。

進程內存的分配與回收

創建進程fork()、程序載入execve()、映射文件mmap()、動態內存分配malloc()/brk()等進程相關操作都需要分配內存給進程。不過這時進程申請和獲得的還不是實際內存,而是虛擬內存,准確的說是「內存區域」。進程對內存區域的分配最終都會歸結到do_mmap()函數上來(brk調用被單獨以系統調用實現,不用do_mmap()),

內核使用do_mmap()函數創建一個新的線性地址區間。但是說該函數創建了一個新VMA並不非常准確,因為如果創建的地址區間和一個已經存在的地址區間相鄰,並且它們具有相同的訪問許可權的話,那麼兩個區間將合並為一個。如果不能合並,那麼就確實需要創建一個新的VMA了。但無論哪種情況,do_mmap()函數都會將一個地址區間加入到進程的地址空間中--無論是擴展已存在的內存區域還是創建一個新的區域。

同樣,釋放一個內存區域應使用函數do_ummap(),它會銷毀對應的內存區域。

如何由虛變實!

從上面已經看到進程所能直接操作的地址都為虛擬地址。當進程需要內存時,從內核獲得的僅僅是虛擬的內存區域,而不是實際的物理地址,進程並沒有獲得物理內存(物理頁面——頁的概念請大家參考硬體基礎一章),獲得的僅僅是對一個新的線性地址區間的使用權。實際的物理內存只有當進程真的去訪問新獲取的虛擬地址時,才會由「請求頁機制」產生「缺頁」異常,從而進入分配實際頁面的常式。

該異常是虛擬內存機制賴以存在的基本保證——它會告訴內核去真正為進程分配物理頁,並建立對應的頁表,這之後虛擬地址才實實在在地映射到了系統的物理內存上。(當然,如果頁被換出到磁碟,也會產生缺頁異常,不過這時不用再建立頁表了)

這種請求頁機制把頁面的分配推遲到不能再推遲為止,並不急於把所有的事情都一次做完(這種思想有點像設計模式中的代理模式(proxy))。之所以能這么做是利用了內存訪問的「局部性原理」,請求頁帶來的好處是節約了空閑內存,提高了系統的吞吐率。要想更清楚地了解請求頁機制,可以看看《深入理解linux內核》一書。

這里我們需要說明在內存區域結構上的nopage操作。當訪問的進程虛擬內存並未真正分配頁面時,該操作便被調用來分配實際的物理頁,並為該頁建立頁表項。在最後的例子中我們會演示如何使用該方法。

系統物理內存管理

雖然應用程序操作的對象是映射到物理內存之上的虛擬內存,但是處理器直接操作的卻是物理內存。所以當應用程序訪問一個虛擬地址時,首先必須將虛擬地址轉化成物理地址,然後處理器才能解析地址訪問請求。地址的轉換工作需要通過查詢頁表才能完成,概括地講,地址轉換需要將虛擬地址分段,使每段虛地址都作為一個索引指向頁表,而頁表項則指向下一級別的頁表或者指向最終的物理頁面。

每個進程都有自己的頁表。進程描述符的pgd域指向的就是進程的頁全局目錄。下面我們借用《linux設備驅動程序》中的一幅圖大致看看進程地址空間到物理頁之間的轉換關系。

上面的過程說起來簡單,做起來難呀。因為在虛擬地址映射到頁之前必須先分配物理頁——也就是說必須先從內核中獲取空閑頁,並建立頁表。下面我們介紹一下內核管理物理內存的機制。

物理內存管理(頁管理)

Linux內核管理物理內存是通過分頁機制實現的,它將整個內存劃分成無數個4k(在i386體系結構中)大小的頁,從而分配和回收內存的基本單位便是內存頁了。利用分頁管理有助於靈活分配內存地址,因為分配時不必要求必須有大塊的連續內存[3],系統可以東一頁、西一頁的湊出所需要的內存供進程使用。雖然如此,但是實際上系統使用內存時還是傾向於分配連續的內存塊,因為分配連續內存時,頁表不需要更改,因此能降低TLB的刷新率(頻繁刷新會在很大程度上降低訪問速度)。

鑒於上述需求,內核分配物理頁面時為了盡量減少不連續情況,採用了「夥伴」關系來管理空閑頁面。夥伴關系分配演算法大家應該不陌生——幾乎所有操作系統方面的書都會提到,我們不去詳細說它了,如果不明白可以參看有關資料。這里只需要大家明白Linux中空閑頁面的組織和管理利用了夥伴關系,因此空閑頁面分配時也需要遵循夥伴關系,最小單位只能是2的冪倍頁面大小。內核中分配空閑頁面的基本函數是get_free_page/get_free_pages,它們或是分配單頁或是分配指定的頁面(2、4、8…512頁)。

注意:get_free_page是在內核中分配內存,不同於malloc在用戶空間中分配,malloc利用堆動態分配,實際上是調用brk()系統調用,該調用的作用是擴大或縮小進程堆空間(它會修改進程的brk域)。如果現有的內存區域不夠容納堆空間,則會以頁面大小的倍數為單位,擴張或收縮對應的內存區域,但brk值並非以頁面大小為倍數修改,而是按實際請求修改。因此Malloc在用戶空間分配內存可以以位元組為單位分配,但內核在內部仍然會是以頁為單位分配的。

另外,需要提及的是,物理頁在系統中由頁結構structpage描述,系統中所有的頁面都存儲在數組mem_map[]中,可以通過該數組找到系統中的每一頁(空閑或非空閑)。而其中的空閑頁面則可由上述提到的以夥伴關系組織的空閑頁鏈表(free_area[MAX_ORDER])來索引。

內核內存使用

Slab

所謂尺有所長,寸有所短。以頁為最小單位分配內存對於內核管理系統中的物理內存來說的確比較方便,但內核自身最常使用的內存卻往往是很小(遠遠小於一頁)的內存塊——比如存放文件描述符、進程描述符、虛擬內存區域描述符等行為所需的內存都不足一頁。這些用來存放描述符的內存相比頁面而言,就好比是麵包屑與麵包。一個整頁中可以聚集多個這些小塊內存;而且這些小塊內存塊也和麵包屑一樣頻繁地生成/銷毀。

為了滿足內核對這種小內存塊的需要,Linux系統採用了一種被稱為slab分配器的技術。Slab分配器的實現相當復雜,但原理不難,其核心思想就是「存儲池[4]」的運用。內存片段(小塊內存)被看作對象,當被使用完後,並不直接釋放而是被緩存到「存儲池」里,留做下次使用,這無疑避免了頻繁創建與銷毀對象所帶來的額外負載。

Slab技術不但避免了內存內部分片(下文將解釋)帶來的不便(引入Slab分配器的主要目的是為了減少對夥伴系統分配演算法的調用次數——頻繁分配和回收必然會導致內存碎片——難以找到大塊連續的可用內存),而且可以很好地利用硬體緩存提高訪問速度。

Slab並非是脫離夥伴關系而獨立存在的一種內存分配方式,slab仍然是建立在頁面基礎之上,換句話說,Slab將頁面(來自於夥伴關系管理的空閑頁面鏈表)撕碎成眾多小內存塊以供分配,slab中的對象分配和銷毀使用kmem_cache_alloc與kmem_cache_free。

Kmalloc

Slab分配器不僅僅只用來存放內核專用的結構體,它還被用來處理內核對小塊內存的請求。當然鑒於Slab分配器的特點,一般來說內核程序中對小於一頁的小塊內存的請求才通過Slab分配器提供的介面Kmalloc來完成(雖然它可分配32到131072位元組的內存)。從內核內存分配的角度來講,kmalloc可被看成是get_free_page(s)的一個有效補充,內存分配粒度更靈活了。

有興趣的話,可以到/proc/slabinfo中找到內核執行現場使用的各種slab信息統計,其中你會看到系統中所有slab的使用信息。從信息中可以看到系統中除了專用結構體使用的slab外,還存在大量為Kmalloc而准備的Slab(其中有些為dma准備的)。

內核非連續內存分配(Vmalloc)

夥伴關系也好、slab技術也好,從內存管理理論角度而言目的基本是一致的,它們都是為了防止「分片」,不過分片又分為外部分片和內部分片之說,所謂內部分片是說系統為了滿足一小段內存區(連續)的需要,不得不分配了一大區域連續內存給它,從而造成了空間浪費;外部分片是指系統雖有足夠的內存,但卻是分散的碎片,無法滿足對大塊「連續內存」的需求。無論何種分片都是系統有效利用內存的障礙。slab分配器使得一個頁面內包含的眾多小塊內存可獨立被分配使用,避免了內部分片,節約了空閑內存。夥伴關系把內存塊按大小分組管理,一定程度上減輕了外部分片的危害,因為頁框分配不在盲目,而是按照大小依次有序進行,不過夥伴關系只是減輕了外部分片,但並未徹底消除。你自己比劃一下多次分配頁面後,空閑內存的剩餘情況吧。

所以避免外部分片的最終思路還是落到了如何利用不連續的內存塊組合成「看起來很大的內存塊」——這里的情況很類似於用戶空間分配虛擬內存,內存邏輯上連續,其實映射到並不一定連續的物理內存上。Linux內核借用了這個技術,允許內核程序在內核地址空間中分配虛擬地址,同樣也利用頁表(內核頁表)將虛擬地址映射到分散的內存頁上。以此完美地解決了內核內存使用中的外部分片問題。內核提供vmalloc函數分配內核虛擬內存,該函數不同於kmalloc,它可以分配較Kmalloc大得多的內存空間(可遠大於128K,但必須是頁大小的倍數),但相比Kmalloc來說,Vmalloc需要對內核虛擬地址進行重映射,必須更新內核頁表,因此分配效率上要低一些(用空間換時間)

與用戶進程相似,內核也有一個名為init_mm的mm_strcut結構來描述內核地址空間,其中頁表項pdg=swapper_pg_dir包含了系統內核空間(3G-4G)的映射關系。因此vmalloc分配內核虛擬地址必須更新內核頁表,而kmalloc或get_free_page由於分配的連續內存,所以不需要更新內核頁表。

vmalloc分配的內核虛擬內存與kmalloc/get_free_page分配的內核虛擬內存位於不同的區間,不會重疊。因為內核虛擬空間被分區管理,各司其職。進程空間地址分布從0到3G(其實是到PAGE_OFFSET,在0x86中它等於0xC0000000),從3G到vmalloc_start這段地址是物理內存映射區域(該區域中包含了內核鏡像、物理頁面表mem_map等等)比如我使用的系統內存是64M(可以用free看到),那麼(3G——3G+64M)這片內存就應該映射到物理內存,而vmalloc_start位置應在3G+64M附近(說"附近"因為是在物理內存映射區與vmalloc_start期間還會存在一個8M大小的gap來防止躍界),vmalloc_end的位置接近4G(說"接近"是因為最後位置系統會保留一片128k大小的區域用於專用頁面映射,還有可能會有高端內存映射區,這些都是細節,這里我們不做糾纏)。

上圖是內存分布的模糊輪廓

由get_free_page或Kmalloc函數所分配的連續內存都陷於物理映射區域,所以它們返回的內核虛擬地址和實際物理地址僅僅是相差一個偏移量(PAGE_OFFSET),你可以很方便的將其轉化為物理內存地址,同時內核也提供了virt_to_phys()函數將內核虛擬空間中的物理映射區地址轉化為物理地址。要知道,物理內存映射區中的地址與內核頁表是有序對應的,系統中的每個物理頁面都可以找到它對應的內核虛擬地址(在物理內存映射區中的)。

而vmalloc分配的地址則限於vmalloc_start與vmalloc_end之間。每一塊vmalloc分配的內核虛擬內存都對應一個vm_struct結構體(可別和vm_area_struct搞混,那可是進程虛擬內存區域的結構),不同的內核虛擬地址被4k大小的空閑區間隔,以防止越界——見下圖)。與進程虛擬地址的特性一樣,這些虛擬地址與物理內存沒有簡單的位移關系,必須通過內核頁表才可轉換為物理地址或物理頁。它們有可能尚未被映射,在發生缺頁時才真正分配物理頁面。

這里給出一個小程序幫助大家認清上面幾種分配函數所對應的區域。

#include<linux/mole.h>

#include<linux/slab.h>

#include<linux/vmalloc.h>

unsignedchar*pagemem;

unsignedchar*kmallocmem;

unsignedchar*vmallocmem;

intinit_mole(void)

{

pagemem = get_free_page(0);

printk("<1>pagemem=%s",pagemem);

kmallocmem = kmalloc(100,0);

printk("<1>kmallocmem=%s",kmallocmem);

vmallocmem = vmalloc(1000000);

printk("<1>vmallocmem=%s",vmallocmem);

}

voidcleanup_mole(void)

{

free_page(pagemem);

kfree(kmallocmem);

vfree(vmallocmem);

}

實例

內存映射(mmap)是Linux操作系統的一個很大特色,它可以將系統內存映射到一個文件(設備)上,以便可以通過訪問文件內容來達到訪問內存的目的。這樣做的最大好處是提高了內存訪問速度,並且可以利用文件系統的介面編程(設備在Linux中作為特殊文件處理)訪問內存,降低了開發難度。許多設備驅動程序便是利用內存映射功能將用戶空間的一段地址關聯到設備內存上,無論何時,只要內存在分配的地址范圍內進行讀寫,實際上就是對設備內存的訪問。同時對設備文件的訪問也等同於對內存區域的訪問,也就是說,通過文件操作介面可以訪問內存。Linux中的X伺服器就是一個利用內存映射達到直接高速訪問視頻卡內存的例子。

熟悉文件操作的朋友一定會知道file_operations結構中有mmap方法,在用戶執行mmap系統調用時,便會調用該方法來通過文件訪問內存——不過在調用文件系統mmap方法前,內核還需要處理分配內存區域(vma_struct)、建立頁表等工作。對於具體映射細節不作介紹了,需要強調的是,建立頁表可以採用remap_page_range方法一次建立起所有映射區的頁表,或利用vma_struct的nopage方法在缺頁時現場一頁一頁的建立頁表。第一種方法相比第二種方法簡單方便、速度快,但是靈活性不高。一次調用所有頁表便定型了,不適用於那些需要現場建立頁表的場合——比如映射區需要擴展或下面我們例子中的情況。

我們這里的實例希望利用內存映射,將系統內核中的一部分虛擬內存映射到用戶空間,以供應用程序讀取——你可利用它進行內核空間到用戶空間的大規模信息傳輸。因此我們將試圖寫一個虛擬字元設備驅動程序,通過它將系統內核空間映射到用戶空間——將內核虛擬內存映射到用戶虛擬地址。從上一節已經看到Linux內核空間中包含兩種虛擬地址:一種是物理和邏輯都連續的物理內存映射虛擬地址;另一種是邏輯連續但非物理連續的vmalloc分配的內存虛擬地址。我們的例子程序將演示把vmalloc分配的內核虛擬地址映射到用戶地址空間的全過程。

程序里主要應解決兩個問題:

第一是如何將vmalloc分配的內核虛擬內存正確地轉化成物理地址?

因為內存映射先要獲得被映射的物理地址,然後才能將其映射到要求的用戶虛擬地址上。我們已經看到內核物理內存映射區域中的地址可以被內核函數virt_to_phys轉換成實際的物理內存地址,但對於vmalloc分配的內核虛擬地址無法直接轉化成物理地址,所以我們必須對這部分虛擬內存格外「照顧」——先將其轉化成內核物理內存映射區域中的地址,然後在用virt_to_phys變為物理地址。

轉化工作需要進行如下步驟:

  • 找到vmalloc虛擬內存對應的頁表,並尋找到對應的頁表項。

  • 獲取頁表項對應的頁面指針

  • 通過頁面得到對應的內核物理內存映射區域地址。

  • 如下圖所示:

    第二是當訪問vmalloc分配區時,如果發現虛擬內存尚未被映射到物理頁,則需要處理「缺頁異常」。因此需要我們實現內存區域中的nopaga操作,以能返回被映射的物理頁面指針,在我們的實例中就是返回上面過程中的內核物理內存映射區域中的地址。由於vmalloc分配的虛擬地址與物理地址的對應關系並非分配時就可確定,必須在缺頁現場建立頁表,因此這里不能使用remap_page_range方法,只能用vma的nopage方法一頁一頁的建立。

    程序組成

    map_driver.c,它是以模塊形式載入的虛擬字元驅動程序。該驅動負責將一定長的內核虛擬地址(vmalloc分配的)映射到設備文件上。其中主要的函數有——vaddress_to_kaddress()負責對vmalloc分配的地址進行頁表解析,以找到對應的內核物理映射地址(kmalloc分配的地址);map_nopage()負責在進程訪問一個當前並不存在的VMA頁時,尋找該地址對應的物理頁,並返回該頁的指針。

    test.c它利用上述驅動模塊對應的設備文件在用戶空間讀取讀取內核內存。結果可以看到內核虛擬地址的內容(ok!),被顯示在了屏幕上。

    執行步驟

    編譯map_driver.c為map_driver.o模塊,具體參數見Makefile

    載入模塊:insmodmap_driver.o

    生成對應的設備文件

    1在/proc/devices下找到map_driver對應的設備命和設備號:grepmapdrv/proc/devices

    2建立設備文件mknodmapfilec 254 0(在我的系統里設備號為254)

    利用maptest讀取mapfile文件,將取自內核的信息列印到屏幕上。

    7. linux的副進程怎麼標識

    所謂進程其實就是執行中的程序而已,和靜態的程序相比,進程是一個運行態的實體,擁有各種各樣的資源:地址空間(未必使用全部地址空間,而是排布在地址空間上的一段段的memory mappings)、打開的文件、pending的信號、一個或者多個thread of execution,內核中數據實體(例如一個或者多個task_struct實體),內核棧(也是一個或者多個)等。針對進程,我們使用進程ID,也就是pid(process ID)。通過getpid和getppid可以獲取當前進程的pid以及父進程的pid。

    進程中的thread of execution被稱作線程(thread),線程是進程中活躍狀態的實體。一方面進程中所有的線程共享一些資源,另外一方面,線程又有自己專屬的資源,例如有自己的PC值,用戶棧、內核棧,有自己的hw context、調度策略等等。我們一般會說進程調度什麼的,但是實際上線程才是是調度器的基本單位。對於Linux內核,線程的實現是一種特別的存在,和經典的unix都不一樣。在linux中並不區分進程和線程,都是用task_struct來抽象,只不過支持多線程的進程是由一組task_struct來抽象,而這些task_struct會共享一些數據結構(例如內存描述符)。我們用thread ID來唯一標識進程中的線程,POSIX規定線程ID在所屬進程中是唯一的,不過在linux kernel的實現中,thread ID是全系統唯一的,當然,考慮到可移植性,Application software不應該假設這一點。在用戶空間,通過gettid函數可以獲取當前線程的thread ID。對於單線程的進程,process ID和thread ID是一樣的,對於支持多線程的進程,每個線程有自己的thread ID,但是所有的線程共享一個PID。

    為了方便shell進行Job controll,我們需要把一組進程組織起來形成進程組。關於這方面的概念,在進程和終端文檔中描述的很詳細,這里就不贅述了。為了標識進程組,我們需要引入進程組ID的概念。我們一般把進程組中的第一個進程的ID作為進程組的ID,進程組中的所有進程共享一個進程組ID。在用戶空間,通過setpgid、getpgid、setpgrp和getpgrp等介面函數可以訪問process group ID。

    經過thread ID、process ID、process group ID的層層遞進,我們終於來到最頂層的ID,也就是session ID,這個ID實際上是用來標識計算機系統中的一次用戶交互過程:用戶登錄入系統,不斷的提交任務(即Job或者說是進程組)給計算機系統並觀察結果,最後退出登錄,銷毀該session。關於session的概念,在進程和終端文檔中描述的也很詳細,大家可以參考那份文檔,這里就不贅述了。在用戶空間,我們可以通過getsid、setsid來操作session ID。

    用戶空間如何看到process ID

    我們用下面這個block diagram來描述用戶空間和內核空間如何看待process ID的:

    8. 進程和線程有什麼區別

    1、功能不同

    進程是計算機中的程序關於某數據集合上的一次運行活動,是系統進行資源分配和調度的基本單位,是操作系統結構的基礎。

    線程是操作系統能夠進行運算調度的最小單位。它被包含在進程之中,是進程中的實際運作單位。

    2、工作原理不同

    在早期面向進程設計的計算機結構中,進程是程序的基本執行實體;在當代面向線程設計的計算機結構中,進程是線程的容器。程序是指令、數據及其組織形式的描述,進程是程序的實體。

    線程是獨立調度和分派的基本單位。線程可以為操作系統內核調度的內核線程,如Win32線程;由用戶進程自行調度的用戶線程,如Linux平台的POSIX Thread;或者由內核與用戶進程,如Windows 7的線程,進行混合調度。

    3、作用不同

    進程是操作系統中最基本、重要的概念。是多道程序系統出現後,為了刻畫系統內部出現的動態情況,描述系統內部各道程序的活動規律引進的一個概念,所有多道程序設計操作系統都建立在進程的基礎上。

    通常在一個進程中可以包含若干個線程,它們可以利用進程所擁有的資源。在引入線程的操作系統中,通常都是把進程作為分配資源的基本單位,而把線程作為獨立運行和獨立調度的基本單位。

    (8)內核數據段區分是哪個進程的嗎擴展閱讀


    進程是由進程式控制制塊,程序段,數據段三部分組成。一個進程可以包含若干線程(Thread),線程可以幫助應用程序同時做幾件事(比如一個線程向磁碟寫入文件,另一個則接收用戶的按鍵操作並及時做出反應,互相不幹擾)。

    在程序被運行後,系統首先要做的就是為該程序進程建立一個默認線程,然後程序可以根據需要自行添加或刪除相關的線程。是可並發執行的程序。

    在一個數據集合上的運行過程,是系統進行資源分配和調度的一個獨立單位,也是稱活動、路徑或任務,它有兩方面性質:活動性、並發性。

    進程可以劃分為運行,阻塞,就緒三種狀態,並隨一定條件而相互轉化,就緒運行,運行阻塞,阻塞就緒。

    進程為應用程序的運行實例,是應用程序的一次動態執行。看似高深,我們可以簡單地理解為:它是操作系統當前運行的執行程序。

    在系統當前運行的執行程序里包括:系統管理計算機個體和完成各種操作所必需的程序;用戶開啟、執行的額外程序,當然也包括用戶不知道,而自動運行的非法程序(它們就有可能是病毒程序)。

    9. 判斷Linux 進程運行在哪個 CPU 內核上的 4 個方法

    1、 如果一個進程使用 taskset 命令明確的被固定(pinned)到 CPU 的特定內核上,你可以使用 taskset 命令找被固定的 CPU 內核:
    $ taskset -c -p <pid>
    例如, 如果你對 PID 5357 這個進程有興趣:
    $ taskset -c -p 5357
    pid 5357's current affinity list: 5
    輸出顯示這個過程被固定在 CPU 內核 5上。
    但是,如果你沒有明確固定進程到任何 CPU 內核,你會得到類似下面的親和力列表。
    pid 5357's current affinity list: 0-11

    2、ps命令可以告訴你每個進程/線程目前分配到的 (在「PSR」列)CPU ID。
    $ ps -o pid,psr,comm -p <pid>
    PID PSR COMMAND
    5357 10 prog
    輸出表示進程的 PID 為 5357(名為」prog」)目前在CPU 內核 10 上運行著。如果該過程沒有被固定,PSR 列會根據內核可能調度該進程到不同內核而改變顯示。

    3、top 命令也可以顯示 CPU 被分配給哪個進程。首先,在top 命令中使用「P」選項。然後按「f」鍵,顯示中會出現 「Last used CPU」 列。目前使用的 CPU 內核將出現在 「P」(或「PSR」)列下。

    4、從命令行啟動 htop。按 鍵,進入」Columns」,在」Available Columns」下會添加 PROCESSOR。

    10. linux 內核空間有進程的概念嗎

    關於內核空間和用戶空間,說的是linux驅動程序一般工作在內核空間,但也可以工作在用戶空間。下面將詳細解析,什麼是內核空間,什麼是用戶空間,以及如何判斷他們。
    Linux簡化了分段機制,使得虛擬地址與線性地址總是一致,因此,Linux的虛擬地址空間也為0~4G.Linux內核將這4G位元組的空間分為兩部分。將最高的1G位元組(從虛擬地址0xC0000000到0xFFFFFFFF),供內核使用,稱為"內核空間".而將較低的3G位元組(從虛擬地址 0x00000000到0xBFFFFFFF),供各個進程使用,稱為"用戶空間)。因為每個進程可以通過系統調用進入內核,因此,Linux內核由系統內的所有進程共享。於是,從具體進程的角度來看,每個進程可以擁有4G位元組的虛擬空間。
    Linux使用兩級保護機制:0級供內核使用,3級供用戶程序使用。每個進程有各自的私有用戶空間(0~3G),這個空間對系統中的其他進程是不可見的。最高的1GB位元組虛擬內核空間則為所有進程以及內核所共享。
    內核空間中存放的是內核代碼和數據,而進程的用戶空間中存放的是用戶程序的代碼和數據。不管是內核空間還是用戶空間,它們都處於虛擬空間中。

    閱讀全文

    與內核數據段區分是哪個進程的嗎相關的資料

    熱點內容
    微信1元3包紅包尾數概率分析 瀏覽:799
    如何改變網站名稱 瀏覽:919
    熊貓看書哪個文件夾 瀏覽:650
    win10勒索文件保護設置 瀏覽:842
    arcgissde93安裝教程 瀏覽:487
    xml文件注釋快捷鍵 瀏覽:878
    extjs的配置文件怎麼配置重定向 瀏覽:740
    access資料庫查看aspx 瀏覽:154
    數控編程如何減少時間 瀏覽:779
    蘋果FLAC屬性 瀏覽:642
    硬碟評分工具 瀏覽:734
    為什麼e福州app登不上 瀏覽:963
    jsfoutputlink 瀏覽:472
    哪個網站可以聽南音 瀏覽:264
    蘋果裝系統裝win7驅動 瀏覽:686
    php判斷file是否有文件 瀏覽:979
    和平精英使用什麼編程開發 瀏覽:102
    f3文件 瀏覽:523
    快手3d環繞音樂用什麼app 瀏覽:376
    linux新增一個文件 瀏覽:440

    友情鏈接