Linux操作系統(tǒng)原理與應(yīng)用_第1頁
Linux操作系統(tǒng)原理與應(yīng)用_第2頁
Linux操作系統(tǒng)原理與應(yīng)用_第3頁
Linux操作系統(tǒng)原理與應(yīng)用_第4頁
Linux操作系統(tǒng)原理與應(yīng)用_第5頁
已閱讀5頁,還剩313頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

Linux操作系統(tǒng)原理與應(yīng)用Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第1頁!章操作系統(tǒng)概述認(rèn)識(shí)操作系統(tǒng)操作系統(tǒng)的發(fā)展開放源代碼的Unix/Linux操作系統(tǒng)Linux內(nèi)核Linux內(nèi)核源代碼

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第2頁!不同角度看到的操作系統(tǒng)操作系統(tǒng)整體看操作系統(tǒng)設(shè)計(jì)者使用者普通開發(fā)者認(rèn)識(shí)操作系統(tǒng)Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第3頁!拷貝命令的C語言實(shí)現(xiàn)片斷<>inf=open(“/floppy/TEST”,O_RDONLY,0);out=open(“/mydir/test”,O_WRONLY,0600);do{l=read(inf,buf,4096);write(outf,buf,l);}while(l);close(outf);close(inf);認(rèn)識(shí)操作系統(tǒng)-從程序開發(fā)者的角度看

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第4頁!操作系統(tǒng)是其它所有用戶程序運(yùn)行的基礎(chǔ)。

<>#include<stdio.h>main(){printf(“Helloworld\n”)}用戶告訴操作系統(tǒng)執(zhí)行test程序操作系統(tǒng)通過文件名找到該程序檢查其類型,檢查程序首部,找出代碼和數(shù)據(jù)存放的地址文件系統(tǒng)找到個(gè)磁盤塊操作系統(tǒng)建立程序的執(zhí)行環(huán)境操作系統(tǒng)把程序從磁盤裝入內(nèi)存,并跳到程序開始處執(zhí)行該程序的執(zhí)行過程簡(jiǎn)述如下:操作系統(tǒng)檢查字符串的位置是否正確操作系統(tǒng)找到字符串被送往的設(shè)備操作系統(tǒng)將字符串送往輸出設(shè)備窗口系統(tǒng)確定這是一個(gè)合法的操作,然后將字符串轉(zhuǎn)換成像素窗口系統(tǒng)將像素寫入存儲(chǔ)映像區(qū)視頻硬件將像素表示轉(zhuǎn)換成一組模擬信號(hào)控制顯示器(重畫屏幕)顯示器發(fā)射電子束。你在屏幕上看到Helloworld。從中看到什么認(rèn)識(shí)操作系統(tǒng)-從程序執(zhí)行看Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第5頁!操作系統(tǒng)是計(jì)算機(jī)系統(tǒng)中的一個(gè)系統(tǒng)軟件,是一些程序模塊的集合——它們能以盡量有效、合理的方式組織和管理計(jì)算機(jī)的軟硬件資源,合理的組織計(jì)算機(jī)的工作流程,控制程序的執(zhí)行并向用戶提供各種服務(wù)功能,使得用戶能夠靈活、方便、有效的使用計(jì)算機(jī),使整個(gè)計(jì)算機(jī)系統(tǒng)能高效、順暢地運(yùn)行。<>認(rèn)識(shí)操作系統(tǒng)-定義Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第6頁!硬件角度下的操作系發(fā)展軌跡年代硬件特點(diǎn)操作系統(tǒng)特點(diǎn)背景機(jī)械計(jì)算機(jī)時(shí)代17世紀(jì)~20世紀(jì)初1)純機(jī)械結(jié)構(gòu),低速

2)只能進(jìn)行簡(jiǎn)單的數(shù)學(xué)運(yùn)算純手工操作從計(jì)算尺至差分機(jī)到分析機(jī)發(fā)展了數(shù)百年代計(jì)算機(jī)

1946年~50年代末電子管計(jì)算機(jī)1)體積大、能耗高、故障多、價(jià)格貴

2)難以普及應(yīng)用無操作系統(tǒng)

(程序按機(jī)器碼編寫,載體從插件板到卡片與紙帶)1906年發(fā)明電子管

1946ENIAC研制成功

(臺(tái)電子管計(jì)算機(jī))年代硬件特點(diǎn)操作系統(tǒng)特點(diǎn)背景第二代計(jì)算機(jī)

50年代末~60年代中期

晶體管計(jì)算機(jī)1)采用印刷電路

2)穩(wěn)定性與可靠性大大提高

3)批量生產(chǎn)成為可能

4)進(jìn)入實(shí)際應(yīng)用領(lǐng)域但數(shù)量有限1)單道批處理系統(tǒng)

2)操作系統(tǒng)以監(jiān)督軟件形式出現(xiàn)

3)任務(wù)按順序方式處理1947年發(fā)明晶體管第三代計(jì)算機(jī)

60年代中期~70年代初

集成電路計(jì)算機(jī)1)體積減小,性價(jià)比迅速提高

2)小型計(jì)算機(jī)發(fā)展迅速

3)進(jìn)入商業(yè)應(yīng)用

4)尚不適合家庭應(yīng)用的需求1)涌現(xiàn)大批操作系統(tǒng)

多道批處理系統(tǒng)、分時(shí)系統(tǒng)和實(shí)時(shí)系統(tǒng)

2)奠定了現(xiàn)代操作系統(tǒng)的基本框架1958年發(fā)明集成電路

1971年INTEL發(fā)明微處理器硬件角度下的操作系統(tǒng)發(fā)展軌跡Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第7頁!<>主流操作系統(tǒng)系統(tǒng)特點(diǎn)計(jì)算機(jī)語言背景無手工操作無編程語言直接使用機(jī)器代碼1936年圖靈提出圖靈機(jī)單道批處理系統(tǒng)作業(yè)運(yùn)行的監(jiān)督程序編程語言雛形期1957年FORTRAN語言開發(fā)成功多道批處理

分時(shí)系統(tǒng)

實(shí)時(shí)系統(tǒng)

多處理系統(tǒng)操作系統(tǒng)結(jié)構(gòu)確立,分為處理機(jī)管理、內(nèi)存管理、設(shè)備管理、文件管理等模塊1)編程語言大量涌現(xiàn)

2)結(jié)構(gòu)化程序設(shè)計(jì)

3)C語言逐漸60年代的軟件危機(jī)導(dǎo)致軟件工程的發(fā)展

1969年Unix誕生

1972年C語言推出主流操作系統(tǒng)系統(tǒng)特點(diǎn)計(jì)算機(jī)語言背景類Unix系列

WINDOWS系列人機(jī)交互成為主題

1)可視化界面

2)多媒體技面向?qū)ο笳Z言成為主流80年代中期開始面向?qū)ο蠹夹g(shù)逐步發(fā)展網(wǎng)絡(luò)操作系統(tǒng)

分布式操作系統(tǒng)微內(nèi)核技術(shù)興起1)JAVA語言

2)腳本語言興起1995年JAVA推出嵌入式系統(tǒng)單內(nèi)核與微內(nèi)核競(jìng)爭(zhēng)激烈編程工具向跨平臺(tái)方向發(fā)1991年免費(fèi)的操作系統(tǒng)Linux發(fā)布軟件角度下的操作系統(tǒng)發(fā)展軌跡

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第8頁!<>講究效率的單模塊操作系統(tǒng)進(jìn)程管理內(nèi)存管理設(shè)備管理文件管理模塊之間可以互相調(diào)用的單模塊結(jié)構(gòu)Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第9頁!<>追求簡(jiǎn)潔的微內(nèi)核操作系統(tǒng)客戶進(jìn)程進(jìn)程服務(wù)器內(nèi)存服務(wù)器文件服務(wù)器…微內(nèi)核Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第10頁!<>歷史悠久的Unix在MULTICS(1969)的肩上制研制者KenThompson和DennisM.Ritchie

站Unix的誕生還伴有C語言呱呱落地Unix是現(xiàn)代操作系統(tǒng)的代表:安全、可靠、強(qiáng)大的計(jì)算能力Unix的商業(yè)化是一把雙刃劍Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第11頁!<>Linux之父-LinusTorvalds芬蘭、赫爾辛基大學(xué)、1990起始于寫兩個(gè)進(jìn)程然后寫驅(qū)動(dòng)程序、文件系統(tǒng)、任務(wù)切換程序,從而形成一個(gè)操作系統(tǒng)鄒形Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第12頁!<>Linux的肥沃土壤-GNUGNU是GNUIsNotUnix的遞歸縮寫,是自由軟件基金會(huì)的一個(gè)項(xiàng)目。GNU項(xiàng)目產(chǎn)品包括emacs編輯器、著名的GNUC和Gcc編譯器等,這些軟件叫做GNU軟件。GNU軟件和派生工作均適用GNU通用公共許可證,即GPL(GeneralPublicLicense

)Linux的開發(fā)使用了眾多的GUN工具Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第13頁!<>Linux系統(tǒng)或發(fā)布版

符合POSIX標(biāo)準(zhǔn)的操作系統(tǒng)內(nèi)核、Shell和外圍工具。C語言編譯器和其他開發(fā)工具及函數(shù)庫XWindow窗口系統(tǒng)各種應(yīng)用軟件,包括字處理軟件、圖象處理軟件等。Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第14頁!<>Linux內(nèi)核

Linus領(lǐng)導(dǎo)下的開發(fā)小組開發(fā)出的系統(tǒng)內(nèi)核是所有Linux發(fā)布版本的核心內(nèi)核開發(fā)人員一般在百人以上,任何自由程序員都可以提交自己的修改工作。采用郵件列表來進(jìn)行項(xiàng)目管理、交流、錯(cuò)誤報(bào)告有大量的用戶進(jìn)行測(cè)試,正式發(fā)布的代碼質(zhì)量高Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第15頁!<>整個(gè)系統(tǒng)的核心-內(nèi)核

用戶進(jìn)程—運(yùn)行在Linux內(nèi)核之上的一個(gè)龐大軟件集合。系統(tǒng)調(diào)用—內(nèi)核的出口,用戶程序通過它使用內(nèi)核提供的功能。Linux內(nèi)核—操作系統(tǒng)的靈魂,負(fù)責(zé)管理磁盤上的文件、內(nèi)存,負(fù)責(zé)啟動(dòng)并運(yùn)行程序,負(fù)責(zé)從網(wǎng)絡(luò)上接收和發(fā)送數(shù)據(jù)包等等。硬件—包括了Linux安裝時(shí)需要的所有可能的物理設(shè)備。例如,CPU、內(nèi)存、硬盤、網(wǎng)絡(luò)硬件等等。Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第16頁!<>內(nèi)核子系統(tǒng)進(jìn)程調(diào)度-控制著進(jìn)程對(duì)CPU的訪問。內(nèi)存管理-允許多個(gè)進(jìn)程安全地共享主內(nèi)存區(qū)域虛擬文件系統(tǒng)-隱藏各種不同硬件的具體細(xì)節(jié),為所有設(shè)備提供統(tǒng)一的接口。網(wǎng)絡(luò)-提供了對(duì)各種網(wǎng)絡(luò)標(biāo)準(zhǔn)協(xié)議的存取和各種網(wǎng)絡(luò)硬件的支持。進(jìn)程間通信(IPC)-支持進(jìn)程間各種通信機(jī)制,包括共享內(nèi)存、消息隊(duì)列及管道等。Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第17頁!內(nèi)核源代碼結(jié)構(gòu)Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第18頁!“內(nèi)核之旅”網(wǎng)站

./電子雜志欄目是關(guān)于內(nèi)核研究和學(xué)習(xí)的資料期“走入Linux世界”涉獵了操作系統(tǒng)的來龍去脈后與大家攜手步入Linux世界。下載代碼,親手搭建實(shí)驗(yàn)系統(tǒng)。Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第19頁!內(nèi)存尋址-操作系統(tǒng)設(shè)計(jì)的硬件基礎(chǔ)之一操作系統(tǒng)-橫跨軟件和硬件的橋梁內(nèi)存尋址-操作系統(tǒng)設(shè)計(jì)的硬件基礎(chǔ)之一操作系統(tǒng)的設(shè)計(jì)者必須在硬件相關(guān)的代碼與硬件無關(guān)的代碼之間劃出清楚的界限,以便于一個(gè)操作系統(tǒng)很容易地移植到不同的平臺(tái)。在這眾多的平臺(tái)中,大家最熟悉的就是i386,即Intel80386體系結(jié)構(gòu)。因此,我們所介紹的內(nèi)存尋址也是以此為背景。

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第20頁!石器時(shí)期-8位尋址在微處理器的歷史上,款微處理器芯片4004是由Intel推出的,4位。在4004之后,intel推出了一款8位處理器叫8080,它有1個(gè)主累加器(寄存器A)和6個(gè)次累加器(寄存器B,C,D,E,H和L)那時(shí)沒有段的概念,訪問內(nèi)存都要通過絕對(duì)地址,因此程序中的地址必須進(jìn)行硬編碼(給出具體地址),而且也難以重定位Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第21頁!白銀時(shí)期-“保護(hù)模式”的引入intel的80286處理器于1982年問世。地址總線位數(shù)增加到了24位。從此開始引進(jìn)了一個(gè)全新理念—保護(hù)模式

訪問內(nèi)存時(shí)不能直接從段寄存器中獲得段的起始地址了,而需要經(jīng)過額外轉(zhuǎn)換和檢查。80286處理器一些致命的缺陷注定不能長(zhǎng)久,它很快被天資卓越的兄弟——80386代替了Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第22頁!IA32寄存器簡(jiǎn)介

·

把16位的通用寄存器、標(biāo)志寄存器以及指令指針寄存器擴(kuò)充為32位的寄存器·段寄存器仍然為16位?!ぴ黾?個(gè)32位的控制寄存器·增加4個(gè)系統(tǒng)地址寄存器·增加8個(gè)調(diào)式寄存器·增加2個(gè)測(cè)試寄存器Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第23頁!常用寄存器簡(jiǎn)介

指令指針寄存器

指令指針寄存器EIP中存放下一條將要執(zhí)行指令的偏移量(offset),這個(gè)偏移量是相對(duì)于目前正在運(yùn)行的代碼段寄存器CS而言的。偏移量加上當(dāng)前代碼段的基地址,就形成了下一條指令的地址。EIP中的低16位可以被單獨(dú)訪問,給它起名叫指令指針I(yè)P寄存器,用于16位尋址。標(biāo)志寄存器標(biāo)志寄存器EFLAGS存放有關(guān)處理器的控制標(biāo)志,很多標(biāo)志與16位FLAGS中的標(biāo)志含義一樣。Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第24頁!物理地址、虛擬地址及線性地址

將主板上的物理內(nèi)存條所提供的內(nèi)存空間定義為物理內(nèi)存空間,其中每個(gè)內(nèi)存單元的實(shí)際地址就是物理地址將應(yīng)用程序員看到的內(nèi)存空間定義為虛擬地址空間(或地址空間),其中的地址就叫虛擬地址(或虛地址),一般用“段:偏移量”的形式來描述

線性地址空間是指一段連續(xù)的,不分段的,范圍為0到4GB的地址空間,一個(gè)線性地址就是線性地址空間的一個(gè)絕對(duì)地址。Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第25頁!地址之間的轉(zhuǎn)換-MMU機(jī)制虛擬地址Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第26頁!虛擬-線性地址的轉(zhuǎn)換虛擬地址空間Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第27頁!保護(hù)模式下的其他描述符表簡(jiǎn)介全局描述符表GDT(GloabalDescriptorTable)中斷描述符表IDT(InterruptDescriptorTable)局部描述符表LDT(LocalDescriptorTable)為了加快對(duì)這些表的訪問,Intel設(shè)計(jì)了專門的寄存器,以存放這些表的基地址及表的長(zhǎng)度界限。這些寄存器只供操作系統(tǒng)使用。有關(guān)這些表的詳細(xì)內(nèi)容請(qǐng)參看有關(guān)保護(hù)模式的參考書。Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第28頁!保護(hù)模式下的特權(quán)級(jí)保護(hù)模式提供了四個(gè)特權(quán)級(jí),用0~3四個(gè)數(shù)字表示很多操作系統(tǒng)(包括Linux,Windwos)只使用了其中的最低和最高兩個(gè),即0表示最高特權(quán)級(jí),對(duì)應(yīng)內(nèi)核態(tài);3表示最低特權(quán)級(jí),對(duì)應(yīng)用戶態(tài)。保護(hù)模式規(guī)定,高特權(quán)級(jí)可以訪問低特權(quán)級(jí),而低特權(quán)級(jí)不能隨便訪問高特權(quán)級(jí)。Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第29頁!Linux中的段Linux是怎樣處理段機(jī)制??Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第30頁!分頁機(jī)制-頁表頁表是把線性地址映射到物理地址的一種數(shù)據(jù)結(jié)構(gòu)。

頁表中應(yīng)當(dāng)包含如下內(nèi)容:物理頁面基地址:線性地址空間中的一個(gè)頁裝入內(nèi)存后所對(duì)應(yīng)的物理頁面的起始地址。頁的屬性:表示頁的特性。例如該頁是否在內(nèi)存,是否可被讀出或?qū)懭氲?。頁面的大小?KB,物理頁面基地址需要多少位就可以?

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第31頁!分頁機(jī)制-兩級(jí)頁表為什么要采用兩級(jí)頁表?…………………………頁目錄頁表物理頁面Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第32頁!分頁機(jī)制-硬件保護(hù)機(jī)制對(duì)于頁表,頁的保護(hù)是由屬性部分的U/S標(biāo)志和R/W標(biāo)志來控制的。當(dāng)U/S標(biāo)志為0時(shí),只有處于內(nèi)核態(tài)的操作系統(tǒng)才能對(duì)此頁或頁表進(jìn)行尋址。當(dāng)這個(gè)標(biāo)志為1時(shí),則不管在內(nèi)核態(tài)還是用戶態(tài),總能對(duì)此頁進(jìn)行尋址。此外,與段的三種存取權(quán)限(讀、寫、執(zhí)行)不同,頁的存取權(quán)限只有兩種(讀、寫)。如果頁目錄項(xiàng)或頁表項(xiàng)的讀寫標(biāo)志為0,說明相應(yīng)的頁表或頁是只讀的,否則是可讀寫的。

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第33頁!分頁機(jī)制-分頁示例假如操作系統(tǒng)給一個(gè)正在運(yùn)行的進(jìn)程分配的線性地址空間范圍是0x20000000到0x2003ffff。這個(gè)空間由64頁組成。我們從分配給進(jìn)程的線性地址的最高10位(分頁硬件機(jī)制把它自動(dòng)解釋成頁目錄域)開始。這兩個(gè)地址都以2開頭,后面跟著0,因此高10位有相同的值,即十六進(jìn)制的0x080或十進(jìn)制的128。因此,這兩個(gè)地址的頁目錄域都指向進(jìn)程頁目錄的第129項(xiàng)。相應(yīng)的目錄項(xiàng)中必須包含分配給進(jìn)程的頁表的物理地址,如圖2.13。如果給這個(gè)進(jìn)程沒有分配其它的線性地址,則頁目錄的其余1023項(xiàng)都為0,也就是這個(gè)進(jìn)程在頁目錄中只占一項(xiàng)。Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第34頁!分頁機(jī)制-頁面高速緩存

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第35頁!分頁機(jī)制-Linux中的分頁Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第36頁!Linux系統(tǒng)地址映射示例Linux采用分頁存儲(chǔ)管理。虛擬地址空間劃分成固定大小的“頁”,由MMU在運(yùn)行時(shí)將虛擬地址映射(變換)成某個(gè)物理頁面中的地址IA32的MMU對(duì)程序中的虛擬地址先進(jìn)行段式映射(虛擬地址轉(zhuǎn)換為線性地址),然后才能進(jìn)行頁式映射(線性地址轉(zhuǎn)換為物理地址)Linux巧妙地使段式映射實(shí)際上不起什么作用Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第37頁!Linux系統(tǒng)地址映射示例用Linux的實(shí)用程序objdump對(duì)其可執(zhí)行代碼進(jìn)行反匯編:%objdump–dhello08048568<greeting>:8048568:pushl%ebp8048569:movl%esp,%ebp804856b:pushl$0x8094048048570:call8048474<_init+0x84>8048575:addl$0x4,%esp8048578:leave8048579:ret804857a:movl%esi,%esi0804857c<main>:804857c:pushl%ebp804857d:movl%esp,%ebp804857f:call8048568<greeting>8048584:leave8048585:ret8048586:nop8048587:nopLinux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第38頁!本章小節(jié)內(nèi)存尋址的演變段機(jī)制分頁機(jī)制Linux中的匯編語言Linux系統(tǒng)地址映射示例

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第39頁!第三章進(jìn)程進(jìn)程介紹進(jìn)程控制塊

進(jìn)程的組織方式進(jìn)程調(diào)度進(jìn)程的創(chuàng)建與進(jìn)程相關(guān)的系統(tǒng)調(diào)用及其應(yīng)用

與調(diào)度相關(guān)的系統(tǒng)調(diào)用及應(yīng)用

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第40頁!進(jìn)程介紹-進(jìn)程層次結(jié)構(gòu)initABCDELinux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第41頁!進(jìn)程介紹-進(jìn)程示例#include<sys/types.h>/*提供類型pid_t的定義,在PC機(jī)上與int型相同*/#include<unistd.h>

/*提供系統(tǒng)調(diào)用的定義*/

main(){pid_tpid;

/*此時(shí)僅有一個(gè)進(jìn)程*/

printf(“PIDbeforefork():%d\n”,(int)getpid());pid=fork();

/*此時(shí)已經(jīng)有兩個(gè)進(jìn)程在同時(shí)運(yùn)行*/

if(pid<0) printf("errorinfork!"); elseif(pid==0) printf("Iamthechildprocess,myprocessIDis%d\n",getpid()); else printf("Iamtheparentprocess,myprocessIDis%d\n",getpid());}

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第42頁!進(jìn)程控制塊對(duì)進(jìn)程進(jìn)行全面描述的數(shù)據(jù)結(jié)構(gòu)

Linux中把對(duì)進(jìn)程的描述結(jié)構(gòu)叫做task_struct:structtask_struct{ … …}傳統(tǒng)上,這樣的數(shù)據(jù)結(jié)構(gòu)被叫做進(jìn)程控制塊PCB(processcontrolblaock)Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第43頁!進(jìn)程控制塊-Linux進(jìn)程狀態(tài)及轉(zhuǎn)換fork()TASK_RUNNING就緒TASK_INTERRUPTIBLE淺度睡眠TASK_UNINTERRUPTIBLE深度睡眠TASK_STOPPED暫停TASK_ZOMBIE僵死占有CPU執(zhí)行do_exit()schedule()ptrace()schedule()時(shí)間片耗盡等待資源到位sleep_on()schedule()等待資源到位interruptible_sleep_on()schedule()資源到位wake_up_interruptible()或收到信號(hào)wake_up()資源到位wake_up()收到信號(hào)SIGCONTwake_up()Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第44頁!進(jìn)程控制塊-進(jìn)程之間的親屬關(guān)系

父進(jìn)程兄進(jìn)程進(jìn)程P弟進(jìn)程指向父進(jìn)程

指向兄進(jìn)程

指向子進(jìn)程

指向弟進(jìn)程

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第45頁!進(jìn)程控制塊-如何存放C語言使用下列的聯(lián)合結(jié)構(gòu)表示這樣一個(gè)混合結(jié)構(gòu):

uniontask_union{structtask_structtask;unsignedlongstack[2408];};Linux調(diào)用alloc_task_struct()函數(shù)分配8KB的task_union內(nèi)存區(qū),調(diào)用free_task_struct()函數(shù)釋放它

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第46頁!進(jìn)程控制塊-如何存放把PCB與內(nèi)核棧放在一起具有以下好處:(1)內(nèi)核可以方便而快速地找到PCB,用偽代碼描述如下:p=(structtask_struct*)STACK_POINTER&0xffffe000

(2)避免在創(chuàng)建進(jìn)程時(shí)動(dòng)態(tài)分配額外的內(nèi)存在Linux中,為了表示當(dāng)前正在運(yùn)行的進(jìn)程,定義了一個(gè)current宏,可以把它看作全局變量來用,例如current->pid返回正在執(zhí)行的進(jìn)程的標(biāo)識(shí)符Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第47頁!進(jìn)程的組織方式-哈希表哈希函數(shù)#definepid_hashfn(x)\((((x)>>8)^(x))&(PIDHASH_SZ-1))

圖為地址法處理沖突時(shí)的哈希表假定哈希表義為:structtask_struct*pidhash[PIDHASH_SZ]

對(duì)給定的PID,如何快速找到對(duì)應(yīng)進(jìn)程?

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第48頁!進(jìn)程的組織方式-等待隊(duì)列等待隊(duì)列表示一組睡眠的進(jìn)程可以把等待隊(duì)列定義為如下結(jié)構(gòu):

structwait_queue{structtask_struct*task;structwait_queue*next;};如何讓正在運(yùn)行的進(jìn)程等待某一特定事件?Linux內(nèi)核中實(shí)現(xiàn)了sleep_on()函數(shù),請(qǐng)給出該函數(shù)的實(shí)現(xiàn)。如果要讓等待的進(jìn)程喚醒,就調(diào)用喚醒函數(shù)wake_up(),它讓待喚醒的進(jìn)程進(jìn)入TASK_RUNNING狀態(tài)。

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第49頁!進(jìn)程調(diào)度-調(diào)度算法時(shí)間片輪轉(zhuǎn)調(diào)度算法系統(tǒng)使每個(gè)進(jìn)程依次地按時(shí)間片輪流地執(zhí)行

優(yōu)先權(quán)調(diào)度算法

非搶占式優(yōu)先權(quán)算法搶占式優(yōu)先權(quán)調(diào)度算法多級(jí)反饋隊(duì)列調(diào)度優(yōu)先權(quán)高的進(jìn)程先運(yùn)行給定的時(shí)間片,相同優(yōu)先權(quán)的進(jìn)程輪流運(yùn)行給定的時(shí)間片實(shí)時(shí)調(diào)度

一般采用搶占式調(diào)度方式Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第50頁!進(jìn)程調(diào)度-調(diào)度時(shí)機(jī)進(jìn)程狀態(tài)轉(zhuǎn)換的時(shí)刻:進(jìn)程終止、進(jìn)程睡眠

當(dāng)前進(jìn)程的時(shí)間片用完時(shí);設(shè)備驅(qū)動(dòng)程序運(yùn)行時(shí);從內(nèi)核態(tài)返回到用戶態(tài)時(shí);

為什么在這些時(shí)機(jī)返回?

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第51頁!進(jìn)程調(diào)度-衡量值得運(yùn)行的程度staticinlineintgoodness(structtask_struct*p,structtask_struct*prev){ intweight;/*權(quán)值,作為衡量進(jìn)程是否運(yùn)行的唯一依據(jù)*/ if(p->police!=SCHED_OTHER)/*實(shí)時(shí)進(jìn)程*/{weight=1000+p->rt_priority;gotoout} weight=p->counter;/*普通進(jìn)程*/if(!weight)/*p用完了時(shí)間片*/gotoout;if(p==prev)/*細(xì)微調(diào)整*/weight+=1;weight+=p->priorityout:returnweight}Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第52頁!調(diào)度函數(shù)schedule()片段如果prev進(jìn)程時(shí)間片用完,而且還是實(shí)時(shí)進(jìn)程,就給它分配新的時(shí)間片,并讓它到可運(yùn)行隊(duì)列末尾:

if(prev->policy==SCHED_RR&&!prev->counter){ prev->counter=prev->priority; move_last_runqueue(prev);}Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第53頁!調(diào)度函數(shù)schedule()片段把next初始化為要檢查的個(gè)可運(yùn)行進(jìn)程。

if(prev->state==TASK_RUNNING){

next=prev;

if(prev->policy&SCHED_YIELD){/*自愿放棄CPU*/

prev->policy&=~SCHED_YIELD;

c=0;

}else

c=goodness(prev,prev);

}else{

c=-1000;/*永不選中,運(yùn)行隊(duì)列鏈表只包含init_task*/

next=&init_task;}

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第54頁!調(diào)度函數(shù)schedule()片段現(xiàn)在到了schedule()的結(jié)束部分:如果已選擇了一個(gè)進(jìn)程,進(jìn)程切換必定發(fā)生:if(prev!=next){kstat.context_swtch++;/*統(tǒng)計(jì)進(jìn)程切換的次數(shù)*/switch_to(prev,next);/*從prev切換到next*/}return;

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第55頁!進(jìn)程的創(chuàng)建-fork()進(jìn)程創(chuàng)建函數(shù)fork()和線程創(chuàng)建函數(shù)clone()都調(diào)用內(nèi)核函數(shù)do_fork(),其主要操作:調(diào)用alloc_task_struct()函數(shù)以獲得8KB的uniontask_union內(nèi)存區(qū),用來存放新進(jìn)程的PCB和內(nèi)核棧。讓當(dāng)前指針指向父進(jìn)程的PCB,并把父進(jìn)程PCB的內(nèi)容拷貝到剛剛分配的新進(jìn)程的PCB中。檢查新創(chuàng)建這個(gè)子進(jìn)程后,當(dāng)前用戶所擁有的進(jìn)程數(shù)目沒有超出給他分配的資源的限制。現(xiàn)在,do_fork()已經(jīng)獲得它從父進(jìn)程能利用的幾乎所有的東西;剩下的事情就是集中建立子進(jìn)程的新資源,并讓內(nèi)核知道這個(gè)新進(jìn)程已經(jīng)呱呱落地。Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第56頁!線程-獨(dú)立執(zhí)行的一個(gè)函數(shù)

Linux把線程和進(jìn)程一視同仁,不過線程本身擁有的資源少,共享進(jìn)程的資源,如地址空間。Linux內(nèi)核線程-在內(nèi)核態(tài)下創(chuàng)建、獨(dú)立執(zhí)行的一個(gè)內(nèi)核函數(shù):intkernel_thread(int(*fn)(void*),void*arg,unsignedlongflags){pid_tp;p=clone(0,flags|CLONE_VM);if(p)/*父*/returnp;else{/*子*/fn(arg);exit();}}Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第57頁!幾個(gè)特殊身份的內(nèi)核線程沒事閑逛的0號(hào)進(jìn)程-從無到有誕生的個(gè)線程,執(zhí)行cpu_idle()函數(shù)(省電又少熱)。既是內(nèi)核線程也是1號(hào)用戶進(jìn)程的init。Init進(jìn)程誕生后就不愿意死亡了,它創(chuàng)建和監(jiān)控操作系統(tǒng)外層所有進(jìn)程的活動(dòng)。

還有另外四個(gè)線程:kflushd(即bdflush)線程:刷新“臟”緩沖區(qū)中的內(nèi)容到磁盤以歸還內(nèi)存。Kupdate線程:刷新舊的“臟”緩沖區(qū)中的內(nèi)容到磁盤以減少文件系統(tǒng)不一致的風(fēng)險(xiǎn)。Kpiod線程:把屬于共享內(nèi)存映射的頁面交換出去。Kswapd線程:執(zhí)行內(nèi)存回收功能。

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第58頁!進(jìn)程的一生隨著一句fork,一個(gè)新進(jìn)程呱呱落地,但這時(shí)它只是老進(jìn)程的一個(gè)克隆。然后,隨著exec,新進(jìn)程脫胎換骨,離家獨(dú)立,開始了獨(dú)立工作的職業(yè)生涯。人有生老病死,進(jìn)程也一樣,它可以是自然死亡,即運(yùn)行到main函數(shù)的最后一個(gè)"}",從容地離我們而去;也可以是中途退場(chǎng),退場(chǎng)有2種方式,一種是調(diào)用exit函數(shù),一種是在main函數(shù)內(nèi)使用return,無論哪一種方式,它都可以留下留言,放在返回值里保留下來;甚至它還可能被謀殺,被其它進(jìn)程通過另外一些方式結(jié)束它的生命。進(jìn)程死掉以后,會(huì)留下一個(gè)空殼,wait站好最后一班崗,打掃戰(zhàn)場(chǎng),使其最終歸于無形。這就是進(jìn)程完整的一生。Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第59頁!小節(jié)進(jìn)程是一個(gè)抽象概念,是對(duì)程序執(zhí)行過程的抽象進(jìn)程控制塊是進(jìn)程這一抽象概念在計(jì)算機(jī)中的描述

進(jìn)程的組織采用了樹、鏈表,哈希表,隊(duì)列等。Linux采用了時(shí)間片輪轉(zhuǎn)的優(yōu)先級(jí)調(diào)度方式進(jìn)程采用“寫時(shí)復(fù)制”技術(shù)創(chuàng)建一個(gè)新進(jìn)程程序開發(fā)人員可以改變進(jìn)程的優(yōu)先級(jí),甚至調(diào)度策略進(jìn)程從誕生到死亡涉及四種系統(tǒng)調(diào)用Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第60頁!內(nèi)存的層次結(jié)構(gòu)Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第61頁!虛地址到實(shí)地址轉(zhuǎn)換虛擬地址Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第62頁!虛擬內(nèi)存-共4G字節(jié),分為內(nèi)核空間(最高的1G字節(jié))和用戶空間(較低的3G字節(jié))兩部分,每個(gè)進(jìn)程最大擁有3G字節(jié)私有虛存空間地址轉(zhuǎn)換-通過頁表把虛存空間的一個(gè)地址轉(zhuǎn)換為物理空間中的實(shí)際地址。虛擬內(nèi)存、內(nèi)核空間和用戶空間Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第63頁!03G4G0X虛擬地址空間

物理內(nèi)存圖4.1內(nèi)核的虛擬地址空間到物理地址空間的映射內(nèi)核空間到物理內(nèi)存的映射<>Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第64頁!地址映射圖4.2虛擬內(nèi)存實(shí)現(xiàn)機(jī)制及之間的關(guān)系虛擬內(nèi)存實(shí)現(xiàn)機(jī)制及之間的關(guān)系<>Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第65頁!Linux把進(jìn)程的用戶空間劃分為一個(gè)個(gè)區(qū)間,便于管理一個(gè)進(jìn)程的用戶地址空間主要由mm_struct結(jié)構(gòu)和vm_area_structs結(jié)構(gòu)來描述。mm_struct結(jié)構(gòu)它對(duì)進(jìn)程整個(gè)用戶空間進(jìn)行描述vm_area_structs結(jié)構(gòu)對(duì)用戶空間中各個(gè)區(qū)間(簡(jiǎn)稱虛存區(qū))進(jìn)行描述

進(jìn)程用戶空間<>Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第66頁!域名說明count對(duì)mm_struct結(jié)構(gòu)的引用進(jìn)行計(jì)數(shù)。為了在Linux中實(shí)現(xiàn)線程,內(nèi)核調(diào)用clone派生一個(gè)線程,線程和調(diào)用進(jìn)程共享用戶空間,即mm_struct結(jié)構(gòu),派生后系統(tǒng)會(huì)累加mm_struct中的引用計(jì)數(shù)。pgd進(jìn)程的頁目錄基地址,當(dāng)調(diào)度程序調(diào)度一個(gè)進(jìn)程運(yùn)行時(shí),就將這個(gè)地址轉(zhuǎn)成物理地址,并寫入控制寄存器(CR3)map_count在進(jìn)程的整個(gè)用戶空間中虛存區(qū)的個(gè)數(shù)semaphore對(duì)mm_struct結(jié)構(gòu)進(jìn)行串行訪問所使用的信號(hào)量Start_code,end_code,start_data,end_data進(jìn)程的代碼段和數(shù)據(jù)段的起始地址和終止地址start_brk,brk,start_stack;每個(gè)進(jìn)程都有一個(gè)特殊的地址區(qū)間,這個(gè)區(qū)間就是所謂的堆,也就是圖4.4中的空洞。前兩個(gè)域分別描述堆的起始地址和終止的地址,最后一個(gè)域描述堆棧段的起始地址。arg_start,arg_end,env_start,env_end命令行參數(shù)所在的堆棧部分的起始地址和終止地址;環(huán)境串所在的堆棧部分的起始地址和終止地址rss,total_vm,locked_vm進(jìn)程貯留在物理內(nèi)存中的頁面數(shù),進(jìn)程所需的總頁數(shù),被鎖定在物理內(nèi)存中的頁數(shù)。mmapvm_area_struct虛存區(qū)結(jié)構(gòu)形成一個(gè)單鏈表,其基址由小到大排列mmap_avlvm_area_struct虛存區(qū)結(jié)構(gòu)形成一個(gè)顆AVL平衡樹mmap_cache最近一次用到的虛存區(qū)很可能下一次還要用到,因此,把最近用到的虛存區(qū)結(jié)構(gòu)放入高速緩存,這個(gè)虛存區(qū)就由mmap_cache指向。Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第67頁!域名說明Vm_mm指向虛存區(qū)所在的mm_struct結(jié)構(gòu)的指針。Vm_start,vm_end虛存區(qū)的起始地址和終止地址。Vm_page_prot虛存區(qū)的保護(hù)權(quán)限。Vm_flags虛存區(qū)的標(biāo)志。Vm_next構(gòu)成線性鏈表的指針,按虛存區(qū)基址從小到大排列。vm_avl_height,vm_avl_left,vm_avl_right這3個(gè)域在一起構(gòu)成AVL樹,其中vm_avl_height是該節(jié)點(diǎn)距根節(jié)點(diǎn)的高度,vm_avl_left和vm_avl_right分別是該節(jié)點(diǎn)的左右兩個(gè)子樹。Vm_ops對(duì)虛存區(qū)進(jìn)行操作的函數(shù)。這些給出了可以對(duì)虛存區(qū)中的頁所進(jìn)行的操作。<>Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第68頁!<>相關(guān)數(shù)據(jù)結(jié)構(gòu)之間的關(guān)系示意圖

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第69頁!執(zhí)行一個(gè)進(jìn)程時(shí),其可執(zhí)行映像必須裝入進(jìn)程的用戶地址空間虛存映射:即把文件從磁盤映射到進(jìn)程的用戶空間,對(duì)文件的訪問轉(zhuǎn)化為對(duì)虛存區(qū)的訪問有共享的、私有的虛存映射和匿名映射當(dāng)可執(zhí)行映像映射到進(jìn)程的用戶空間時(shí),將產(chǎn)生一組vm_area_struct結(jié)構(gòu)來描述各虛擬區(qū)間的起始點(diǎn)和終止點(diǎn)虛存映射<>Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第70頁!與用戶空間相關(guān)的主要系統(tǒng)調(diào)用

系統(tǒng)調(diào)用描述fork()創(chuàng)建具有新的用戶空間的進(jìn)程,用戶空間中的所有頁被標(biāo)記為“寫時(shí)復(fù)制”,且由父子進(jìn)程共享,當(dāng)其中的一個(gè)進(jìn)程所訪問的頁不在內(nèi)存時(shí),這個(gè)頁就被復(fù)制一份。mmap()在進(jìn)程的用戶空間內(nèi)創(chuàng)建一個(gè)新的虛存區(qū)。munmap()銷毀一個(gè)完整的虛存區(qū)或其中的一部分,如果要取消的虛存區(qū)位于某個(gè)虛存區(qū)的中間,則這個(gè)虛存區(qū)被劃分為兩個(gè)虛存區(qū)。exec()裝入新的可執(zhí)行文件以代替當(dāng)前用戶空間。Exit()銷毀進(jìn)程的用戶空間及其所有的虛存區(qū)。<>Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第71頁!<>缺頁異常處理程序這個(gè)虛地址屬于進(jìn)程的用戶空間?訪問類型與這個(gè)虛存區(qū)的訪問權(quán)匹配?異常發(fā)生在用戶態(tài)?合法訪問:分配一個(gè)新的頁面非法訪問:發(fā)送一個(gè)SIGSEBV信號(hào)內(nèi)核錯(cuò)誤:殺死進(jìn)程否是是是否否總體方案Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第72頁!請(qǐng)求調(diào)頁:把頁面的分配推遲到進(jìn)程要訪問的頁不在物理內(nèi)存時(shí)為止,由此引起一個(gè)缺頁異常引入原因:進(jìn)程開始運(yùn)行時(shí)并不訪問其地址空間中的全部地址

程序的局部性原理保證請(qǐng)求調(diào)頁從總體上使系統(tǒng)有更大的吞吐量。

<>請(qǐng)求調(diào)頁-動(dòng)態(tài)內(nèi)存分配技術(shù)Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第73頁!在Linux中,CPU所訪問的地址是虛擬地址空間的虛地址;管理內(nèi)存頁面時(shí),先在虛存空間中分配一個(gè)虛存區(qū)間,然后才根據(jù)需要為此區(qū)間分配相應(yīng)的物理頁面并建立起映射

Linux采用著名的伙伴(Buddy)算法來解決外碎片問題

<>物理內(nèi)存的分配與回收

保留內(nèi)核映象動(dòng)態(tài)內(nèi)存00x100000start_memend_memLinux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第74頁!函數(shù)__get_free_pages用于分配物理頁塊該函數(shù)所做的工作如下:檢查所請(qǐng)求的頁塊大小是否能夠被滿足檢查系統(tǒng)中空閑物理頁的總數(shù)是否已低于允許的下界正常分配。從free_area數(shù)組的第order項(xiàng)開始,這是一個(gè)mem_map_t鏈表。換頁。通過下列語句調(diào)用函數(shù)try_to_free_pages(),啟動(dòng)換頁進(jìn)程

<>物理頁面的分配Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第75頁!函數(shù)free_pages用于頁塊的回收

該函數(shù)所做的工作如下:根據(jù)頁塊的首地址addr算出該頁塊的頁在mem_map數(shù)組的索引;如果該頁是保留的(內(nèi)核在使用),則不允許回收;將頁塊頁對(duì)應(yīng)的mem_map_t結(jié)構(gòu)中的count域減1,表示引用該頁的進(jìn)程數(shù)減了1個(gè)。若count域的值不為0,有別的進(jìn)程在使用該頁塊,不能回收,僅簡(jiǎn)單返回清除頁塊頁對(duì)應(yīng)的mem_map_t結(jié)構(gòu)中flags域的PG_referenced位,表示該頁塊不再被引用;將全局變量nr_free_pages的值加上回收的物理頁數(shù)將頁塊加入到數(shù)組free_area的相應(yīng)鏈表中

<>物理頁面的回收Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第76頁!Slab分配模式把對(duì)象分組放進(jìn)緩沖區(qū)

Slab緩沖區(qū)由一連串的“大塊(Slab)”構(gòu)成,每個(gè)大塊中包含若干個(gè)同種類型的對(duì)象,這些對(duì)象或已被分配,或空閑

簡(jiǎn)言之,緩沖區(qū)就是主存中的一片區(qū)域,把這片區(qū)域劃分為多個(gè)塊,每塊就是一個(gè)Slab,每個(gè)Slab由一個(gè)或多個(gè)頁面組成,每個(gè)Slab中存放的就是對(duì)象

<>Slab分配機(jī)制-分配小內(nèi)存Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第77頁!專用緩沖區(qū)主要用于頻繁使用的數(shù)據(jù)結(jié)構(gòu)

緩沖區(qū)是用kmem_cache_t類型描述的,通過kmem_cache_create()來建立

函數(shù)kmem_cache_create()所創(chuàng)建的緩沖區(qū)中還沒有包含任何Slab,因此,也沒有空閑的對(duì)象。只有以下兩個(gè)條件都為真時(shí),才給緩沖區(qū)分配Slab:已發(fā)出一個(gè)分配新對(duì)象的請(qǐng)求;緩沖區(qū)不包含任何空閑對(duì)象;

Slab專用緩沖區(qū)的建立和釋放

<>Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第78頁!在內(nèi)核中初始化開銷不大的數(shù)據(jù)結(jié)構(gòu)可以合用一個(gè)通用的緩沖區(qū)。通用緩沖區(qū)類似于物理頁面分配中的大小分區(qū)對(duì)通用緩沖區(qū)的管理采用Slab方式當(dāng)一個(gè)數(shù)據(jù)結(jié)構(gòu)的使用不頻繁、或其大小不足一個(gè)頁面時(shí),沒有必要給其分配專用緩沖區(qū),可調(diào)用函數(shù)kmallo()分配通用緩沖區(qū)<>通用緩沖區(qū)Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第79頁!vmalloc()與kmalloc()都可用于分配內(nèi)存kmalloc()分配的內(nèi)存處于3GB~high_memory之間,這段內(nèi)核空間與物理內(nèi)存的映射一一對(duì)應(yīng),而vmalloc()分配的內(nèi)存在VMALLOC_START~4GB之間,這段非連續(xù)內(nèi)存區(qū)映射到物理內(nèi)存也可能是非連續(xù)的vmalloc()分配的物理地址無需連續(xù),而kmalloc()確保頁在物理上是連續(xù)的<>vmalloc()與kmalloc()之區(qū)別Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第80頁!在Linux中,進(jìn)行交換的單位是頁面而不是進(jìn)程在頁面交換中,頁面置換算法是影響交換性能的關(guān)鍵性指標(biāo),其復(fù)雜性主要與換出有關(guān):哪種頁面要換出如何在交換區(qū)中存放頁面如何選擇被交換出的頁面<>頁面交換Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第81頁!交換區(qū)也被劃分為塊,每個(gè)塊的大小恰好等于一頁,一塊叫做一個(gè)頁插槽換出時(shí),內(nèi)核盡可能把換出的頁放在相鄰的插槽中,從而減少訪問交換區(qū)時(shí)磁盤的尋道時(shí)間若系統(tǒng)使用了多個(gè)交換區(qū),快速交換區(qū)可以獲得比較高的優(yōu)先級(jí)當(dāng)查找一個(gè)空閑插槽時(shí),要從優(yōu)先級(jí)最高的交換區(qū)中開始搜索如果優(yōu)先級(jí)最高的交換區(qū)不止一個(gè),應(yīng)該循環(huán)選擇相同優(yōu)先級(jí)的交換區(qū)<>在交換區(qū)中存放頁面Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第82頁!釋放頁面。如果一個(gè)頁面變?yōu)榭臻e可用,就把該頁面的page結(jié)構(gòu)鏈入某個(gè)空閑隊(duì)列free_area,同時(shí)頁面的使用計(jì)數(shù)count減1。分配頁面。調(diào)用___get_free_page()從某個(gè)空閑隊(duì)列分配內(nèi)存頁面,并將其頁面的使用計(jì)數(shù)count置為1?;钴S狀態(tài)。已分配的頁面處于活躍狀態(tài),該頁面的數(shù)據(jù)結(jié)構(gòu)page通過其隊(duì)列頭結(jié)構(gòu)lru鏈入活躍頁面隊(duì)列active_list,并且在進(jìn)程地址空間中至少有一個(gè)頁與該頁面之間建立了映射關(guān)系。不活躍“臟”狀態(tài)。處于該狀態(tài)的頁面其page結(jié)構(gòu)通過其隊(duì)列頭結(jié)構(gòu)lru鏈入不活躍“臟”頁面隊(duì)列inactive_dirty_list,并且原則是任何進(jìn)程的頁面表項(xiàng)不再指向該頁面,也就是說,斷開頁面的映射,同時(shí)把頁面的使用計(jì)數(shù)count減1。將不活躍“臟”頁面的內(nèi)容寫入交換區(qū),并將該頁面的page結(jié)構(gòu)從不活躍“臟”頁面隊(duì)列inactive_dirty_list轉(zhuǎn)移到不活躍“干凈”頁面隊(duì)列,準(zhǔn)備被回收。不活躍“干凈”狀態(tài)。頁面page結(jié)構(gòu)通過其隊(duì)列頭結(jié)構(gòu)lru鏈入某個(gè)不活躍“干凈”頁面隊(duì)列。如果在轉(zhuǎn)入不活躍狀態(tài)以后的一段時(shí)間內(nèi),頁面又受到訪問,則又轉(zhuǎn)入活躍狀態(tài)并恢復(fù)映射。當(dāng)需要時(shí),就從“干凈”頁面隊(duì)列中回收頁面,也就是說或者把頁面鏈入到空閑隊(duì)列,或者直接進(jìn)行分配。<>Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第83頁!希望通過訪問用戶空間的內(nèi)存達(dá)到讀取內(nèi)核數(shù)據(jù)的目的,這樣便可進(jìn)行內(nèi)核空間到用戶空間的大規(guī)模信息傳送,從而應(yīng)用于高速數(shù)據(jù)采集等性能要求高的場(chǎng)合從用戶空間直接讀取內(nèi)核數(shù)據(jù),即利用內(nèi)存映射功能,將內(nèi)核中的一部分虛擬內(nèi)存映射到用戶空間,使得訪問用戶空間地址等同于訪問被映射的內(nèi)核空間地址,從而不再需要數(shù)據(jù)拷貝操作

<>內(nèi)存管理實(shí)例Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第84頁!跨空間的地址映射主要包括:找到內(nèi)核地址對(duì)應(yīng)的物理地址,這是為了將用戶頁表項(xiàng)直接指向物理地址;建立新的用戶頁表項(xiàng)<>代碼體系結(jié)構(gòu)介紹

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第85頁!<>mmap系統(tǒng)調(diào)用File->mma(mapdrv_mmap)Vma->nopage(map_nopage)獲得vm_area對(duì)應(yīng)的內(nèi)核邏輯地址(vaddr_to_kaddr)得到內(nèi)核邏輯地址對(duì)應(yīng)的進(jìn)程頁框(virt_to_page)獲得vm_area對(duì)應(yīng)的內(nèi)核頁表項(xiàng)(pgd_offset_kpmd_offsetpte_offset)獲vm_area對(duì)應(yīng)的內(nèi)核邏輯地址(page_address)獲得vm_area對(duì)應(yīng)內(nèi)核頁表項(xiàng)指針(pte_offset)任務(wù)的執(zhí)行路徑Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第86頁!“內(nèi)核之旅”網(wǎng)站./電子雜志欄目是關(guān)于內(nèi)核研究和學(xué)習(xí)的資料第五期“Linux內(nèi)存管理”,從應(yīng)用程序開發(fā)者的角度審視Linux的進(jìn)程內(nèi)存管理,在此基礎(chǔ)上逐步深入到內(nèi)核中討論系統(tǒng)物理內(nèi)存管理和內(nèi)核內(nèi)存的使用方法。力求從外到內(nèi)、水到渠成地引導(dǎo)網(wǎng)友分析Linux的內(nèi)存管理與使用。下載實(shí)例代碼進(jìn)行調(diào)試Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第87頁!中斷控制的主要優(yōu)點(diǎn):CPU只有在I/O需要服務(wù)時(shí)才響應(yīng)外部中斷:外部設(shè)備所發(fā)出的I/O請(qǐng)求內(nèi)部中斷:也稱之為“異?!保菫榻鉀Q機(jī)器運(yùn)行時(shí)所出現(xiàn)的某些隨機(jī)事件及編程方便而出現(xiàn)的<>中斷掠影Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第88頁!中斷向量-每個(gè)中斷源都被分配一個(gè)8位無符號(hào)整數(shù)作為類型碼,即中斷向量中斷的種類:中斷:外部可屏蔽中斷外部非屏蔽中斷異常:不使用中斷控制器,不能被屏蔽故障陷阱<>中斷向量-中斷源的類型Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第89頁!

異常就是CPU內(nèi)部出現(xiàn)的中斷,即在CPU執(zhí)行特定指令時(shí)出現(xiàn)的非法情況。非屏蔽中斷就是計(jì)算機(jī)內(nèi)部硬件出錯(cuò)時(shí)引起的異常情況

Intel把非屏蔽中斷作為一種異常來處理在CPU執(zhí)行一個(gè)異常處理程序時(shí),就不再為其他異?;蚩善帘沃袛嗾?qǐng)求服務(wù)

<>異常及非屏蔽中斷Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第90頁!調(diào)用過程指令CALL:CALL過程名調(diào)用中斷過程的指令I(lǐng)NT

INT中斷向量中斷返回指令I(lǐng)RETIRET

加載中斷描述符表的指令LIDT

LIDT48位的偽描述符<>相關(guān)匯編指令

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第91頁!IDT表項(xiàng)的設(shè)置通過_set_gaet()函數(shù)實(shí)現(xiàn)

調(diào)用該函數(shù)在IDT表中插入一個(gè)中斷門:set_intr_gate(unsignedintn,void*addr)

調(diào)用該函數(shù)在IDT表中插入一個(gè)陷阱門:set_trap_gate(unsignedintn,void*addr)調(diào)用該函數(shù)在IDT表中插入一個(gè)系統(tǒng)門:set_system_gate(unsignedintn,void*addr)

<>IDT表項(xiàng)的設(shè)置Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第92頁!中斷門的設(shè)置是由init_IRQ()函數(shù)中的一段代碼完成的:設(shè)置時(shí)必須跳過用于系統(tǒng)調(diào)用的向量0x80

中斷處理程序的入口地址是一個(gè)數(shù)組interrupt[],數(shù)組中的每個(gè)元素是指向中斷處理函數(shù)的指針。

<>中斷門的設(shè)置for(i=0;i<NR_IRQS;i++){intvector=FIRST_EXTERNAL_VECTOR+i;if(vector!=SYSCALL_VECTOR)set_intr_gate(vector,interrupt[i]);}Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第93頁!當(dāng)CPU執(zhí)行了當(dāng)前指令之后,CS和EIP這對(duì)寄存器中所包含的內(nèi)容就是下一條將要執(zhí)行指令的虛地址。在對(duì)下一條指令執(zhí)行前,CPU先要判斷在執(zhí)行當(dāng)前指令的過程中是否發(fā)生了中斷或異常。如果發(fā)生了一個(gè)中斷或異常,那么CPU將做以下事情:<>中斷和異常的硬件處理

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第94頁!由于硬件條件的限制,很多硬件設(shè)備共享一條中斷線為方便處理,Linux為每條中斷線設(shè)置了一個(gè)中斷請(qǐng)求隊(duì)列中斷服務(wù)例程與中斷處理程序中斷線共享的數(shù)據(jù)結(jié)構(gòu)注冊(cè)中斷服務(wù)例程<>中斷請(qǐng)求隊(duì)列的建立Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第95頁!structirqaction{void(*handler)(int,void*,structpt_regs*);unsignedlongflags;unsignedlongmask;constchar*name;void*dev_id;structirqaction*next;};

Handler:指向一個(gè)具體I/O設(shè)備的中斷服務(wù)例程Flags:用一組標(biāo)志描述中斷線與I/O設(shè)備之間的關(guān)系。SA_INTERRUPT:中斷處理程序執(zhí)行時(shí)必須禁止中斷SA_SHIRQ:允許其它設(shè)備共享這條中斷線。<>中斷線共享的數(shù)據(jù)結(jié)構(gòu)

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第96頁!初始化IDT表之后,必須通過request_irq()函數(shù)將相應(yīng)的中斷服務(wù)例程掛入中斷請(qǐng)求隊(duì)列,即對(duì)其進(jìn)行注冊(cè)

在關(guān)閉設(shè)備時(shí),必須通過調(diào)用free_irq()函數(shù)釋放所申請(qǐng)的中斷請(qǐng)求號(hào)

<>注冊(cè)中斷服務(wù)例程

intrequest_irq(unsignedintirq,void(*handler)(int,void*,structpt_regs*),unsignedlongirqflags,constchar*devname,void*dev_id)Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第97頁!當(dāng)處理所有外設(shè)中斷請(qǐng)求的函數(shù)do_IRQ()執(zhí)行時(shí),內(nèi)核棧頂包含的就是do_IRQ()的返回地址,這個(gè)地址指向ret_from_intr從中斷返回時(shí),CPU要調(diào)用恢復(fù)中斷現(xiàn)場(chǎng)的宏RESTORE_ALL,徹底從中斷返回。

<>從中斷返回Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第98頁!小任務(wù)是指待處理的下半部,其數(shù)據(jù)結(jié)構(gòu)為tasklet_struct,每個(gè)結(jié)構(gòu)代表一個(gè)獨(dú)立的小任務(wù)小任務(wù)既可以靜態(tài)地創(chuàng)建,也可以動(dòng)態(tài)地創(chuàng)建

<>小任務(wù)機(jī)制

structtasklet_struct{Structtasklet_struct*next;unsignedlongstate;atomic_tcount; void(*func)(unsignedlong);unsignedlongdata; };

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第99頁!下半部是一個(gè)不能與其他下半部并發(fā)執(zhí)行的高優(yōu)先級(jí)小任務(wù)

bh_base是一個(gè)指向下半部的指針數(shù)組,用于組織所有下半部

bh_base數(shù)組共有32項(xiàng),每一項(xiàng)都是一種下半部<>下半部

下半部外部設(shè)備TIMER_BH定時(shí)器TQUEUE_BH

周期性任務(wù)隊(duì)列SERIAL_BH

串行端口IMMEDIATE_BH

立即任務(wù)隊(duì)列Linux常用的下半部Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第100頁!大部分PC機(jī)中有兩個(gè)時(shí)鐘源,分別是實(shí)時(shí)時(shí)鐘(RTC)和操作系統(tǒng)(OS)時(shí)鐘實(shí)時(shí)時(shí)鐘也叫硬件時(shí)鐘,它靠電池供電,即使系統(tǒng)斷電,也可以維持日期和時(shí)間。RTC和OS時(shí)鐘之間的關(guān)系通常也被稱作操作系統(tǒng)的時(shí)鐘運(yùn)作機(jī)制不同的操作系統(tǒng),其時(shí)鐘運(yùn)作機(jī)制也不同

<>中斷的應(yīng)用-時(shí)鐘中斷Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第101頁!OS時(shí)鐘是由可編程定時(shí)/計(jì)數(shù)器產(chǎn)生的輸出脈沖觸發(fā)中斷而產(chǎn)生的操作系統(tǒng)的“時(shí)間基準(zhǔn)”由設(shè)計(jì)者決定,Linux的時(shí)間基準(zhǔn)是1970年1月1日凌晨0點(diǎn)OS時(shí)鐘記錄的時(shí)間就是系統(tǒng)時(shí)間。系統(tǒng)時(shí)間以“時(shí)鐘節(jié)拍”為單位Linux中用全局變量jiffies表示系統(tǒng)自啟動(dòng)以來的時(shí)鐘節(jié)拍數(shù)目

<>Linux時(shí)間系統(tǒng)Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第102頁!timer_bh()函數(shù)與TIMER_BH下半部相關(guān)聯(lián),它在每個(gè)時(shí)鐘節(jié)拍都被激活

TIMER_BH下半部以關(guān)中斷調(diào)用update_times()函數(shù),該函數(shù)會(huì)以關(guān)中斷來更新xtime

更新了系統(tǒng)時(shí)鐘xtime之后,update_times()再次打開中斷時(shí)鐘中斷的下半部處理<>Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第103頁!定義定時(shí)器:structtimer_listmy_timer;

初始化定時(shí)器:init_timer(&my_timer);

激活定時(shí)器:add_timer(&my_timer);如果需要在定時(shí)器到期前停止定時(shí)器,可以使用del_timer()函數(shù):del_timer(&my_timer);<>定時(shí)器的使用Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第104頁!timeout=2*HZ;/*1HZ等于100,因此為2000ms*/set_current_state(TASK_INTERRUPTIBLE);remaining=schedule_timeout(timeout); 內(nèi)核用定時(shí)器實(shí)現(xiàn)進(jìn)程的延時(shí),調(diào)用schedule_timeout()函數(shù),該函數(shù)執(zhí)行下列語句:structtimer_listtimer;expire=timeout+jiffies;init_timer(&timer);timer.expires=expire;timer.data=(unsignedlong)current;timer.function=process_timeout;add_timer(&timer);schedule();/*進(jìn)程被掛起直到定時(shí)器到期*/del_timer_sync(&timer);timeout=expire-jiffies;return(timeout<0?0:timeout);當(dāng)延時(shí)到期時(shí),內(nèi)核執(zhí)行下列函數(shù):voidprocess_timeout(unsignedlongdata){ structtask_struct*p=(structtask_struct*)data; wake_up_process(p);}<>Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第105頁!第六章系統(tǒng)調(diào)用系統(tǒng)調(diào)用與API、系統(tǒng)命令、內(nèi)核函數(shù)系統(tǒng)調(diào)用處理程序及服務(wù)例程封裝例程添加新的系統(tǒng)調(diào)用系統(tǒng)調(diào)用實(shí)例Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第106頁!Linux的應(yīng)用編程接口(API)遵循

POSIX標(biāo)準(zhǔn)應(yīng)用編程接口(API)其實(shí)是一組函數(shù)定義,這些函數(shù)說明了如何獲得一個(gè)給定的服務(wù);而系統(tǒng)調(diào)用是通過軟中斷向內(nèi)核發(fā)出一個(gè)明確的請(qǐng)求API有可能和系統(tǒng)調(diào)用的調(diào)用形式一致

API和系統(tǒng)調(diào)用關(guān)注的都是函數(shù)名、參數(shù)類型及返回代碼的含義系統(tǒng)調(diào)用的實(shí)現(xiàn)是在內(nèi)核完成的,而用戶態(tài)的函數(shù)是在函數(shù)庫中實(shí)現(xiàn)的<>系統(tǒng)調(diào)用與APILinux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第107頁!內(nèi)核函數(shù)在形式上與普通函數(shù)一樣,但它是在內(nèi)核實(shí)現(xiàn)的,需要滿足一些內(nèi)核編程的要求

系統(tǒng)調(diào)用是用戶進(jìn)程進(jìn)入內(nèi)核的接口層,它本身并非內(nèi)核函數(shù),但它是由內(nèi)核函數(shù)實(shí)現(xiàn)的進(jìn)入內(nèi)核后,不同的系統(tǒng)調(diào)用會(huì)找到各自對(duì)應(yīng)的內(nèi)核函數(shù),這些內(nèi)核函數(shù)被稱為系統(tǒng)調(diào)用的“服務(wù)例程”

系統(tǒng)調(diào)用與內(nèi)核函數(shù)<>Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第108頁!<>…xyz()…system_call:…sys_xyz()…ret_from_sys_call:…iretxyz(){…int0x80…}sys_xyz(){…}在應(yīng)用程序在libc標(biāo)準(zhǔn)庫系統(tǒng)調(diào)用系統(tǒng)調(diào)用調(diào)用中的中的封裝例程處理程序服務(wù)例程系統(tǒng)調(diào)用用戶態(tài)內(nèi)核態(tài)調(diào)用一個(gè)系統(tǒng)調(diào)用

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第109頁!system_call()函數(shù)實(shí)現(xiàn)了系統(tǒng)調(diào)用處理程序:它首先把系統(tǒng)調(diào)用號(hào)和該異常處理程序用到的所有CPU寄存器保存到相應(yīng)的棧中

把當(dāng)前進(jìn)程PCB的地址存放在ebx中

對(duì)用戶態(tài)進(jìn)程傳遞來的系統(tǒng)調(diào)用號(hào)進(jìn)行有效性檢查。若調(diào)用號(hào)大于或等于NR_syscalls,系統(tǒng)調(diào)用處理程序終止

若系統(tǒng)調(diào)用號(hào)無效,函數(shù)就把-ENOSYS值存放在棧中eax寄存器所在的單元,再跳到ret_from_sys_call()

根據(jù)eax中所包含的系統(tǒng)調(diào)用號(hào)調(diào)用對(duì)應(yīng)的特定服務(wù)例程

<>system_call()函數(shù)Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第110頁!<>跟蹤系統(tǒng)調(diào)用的執(zhí)行

分析系統(tǒng)調(diào)用有兩種方法:

查看entry.s中的代碼細(xì)節(jié),閱讀相關(guān)的源碼來分析其運(yùn)行過程;

借助一些內(nèi)核調(diào)試工具,動(dòng)態(tài)跟蹤執(zhí)行路徑。

結(jié)合用戶空間的執(zhí)行路徑,該程序的執(zhí)行大致可歸結(jié)為以下幾個(gè)步驟:1、程序調(diào)用libc庫的封裝函數(shù)

2、調(diào)用軟中斷int0x80進(jìn)入內(nèi)核。

3、在內(nèi)核中首先執(zhí)行system_call函數(shù),接著根據(jù)系統(tǒng)調(diào)用號(hào)在系統(tǒng)調(diào)用表中查找到對(duì)應(yīng)的系統(tǒng)調(diào)用服務(wù)例程

4、執(zhí)行該服務(wù)例程

5、執(zhí)行完畢后,轉(zhuǎn)入ret_from_sys_call例程,從系統(tǒng)調(diào)用返回

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第111頁!

添加系統(tǒng)調(diào)用的步驟:

添加系統(tǒng)調(diào)用號(hào)。系統(tǒng)調(diào)用號(hào)在unistd.h文件中定義,以“__NR_”開頭

在系統(tǒng)調(diào)用表(在entry.S中)中添加自己的服務(wù)例程sys_mysyscall

實(shí)現(xiàn)系統(tǒng)調(diào)用服務(wù)例程:把sys_mysyscall加在kernel目錄下的系統(tǒng)調(diào)用文件sys.c中

重新編譯內(nèi)核

編寫用戶態(tài)程序<>添加新的系統(tǒng)調(diào)用Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第112頁!

日志記錄例程Syscall_audit():

內(nèi)核態(tài)的服務(wù)例程,負(fù)責(zé)記錄系統(tǒng)調(diào)用的運(yùn)行日志,包括調(diào)用時(shí)刻、調(diào)用者PID、程序名等

服務(wù)例程Sys_audit():

新添加的系統(tǒng)調(diào)用,其功能是從緩沖區(qū)中取數(shù)據(jù)返回用戶空間

用戶空間服務(wù)程序auditd

取回系統(tǒng)中搜集到的系統(tǒng)調(diào)用日志信息

<>代碼結(jié)構(gòu)體系介紹

Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第113頁!

改entry.S匯編代碼,在系統(tǒng)調(diào)用表中加入新的系統(tǒng)調(diào)用,然后在系統(tǒng)調(diào)用入口中加入跳轉(zhuǎn)到日志記錄服務(wù)例程

填加代碼文件audit.c,該文件中包含syscall_audit與系統(tǒng)調(diào)用sys_audit兩個(gè)函數(shù)體

修改i386_ksyms.c文件,在最后加入EXPORT_SYMBOL(my_audit);externint(*my_sysaudit)(unsignedchar,unsignedchar*,unsignedshort,unsignedchar);EXPORT_SYMBOL(my_sysaudit);

<>把代碼集成到內(nèi)核中Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第114頁!

編寫名為audit的模塊

編譯并加載模塊insmodaudit.o

編寫一個(gè)用戶程序deamon循環(huán)調(diào)用audit系統(tǒng)調(diào)用,并把搜集到的信息打印到屏幕上。

<>重新編譯內(nèi)核StepByStepLinux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第115頁!第七章內(nèi)核中的同步臨界區(qū)和競(jìng)爭(zhēng)狀態(tài)內(nèi)核同步措施并發(fā)控制Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第116頁!考慮一個(gè)非常簡(jiǎn)單的共享資源的例子:一個(gè)全局整型變量和一個(gè)簡(jiǎn)單的臨界區(qū),其中的操作僅僅是將整型變量的值增加1:

i++

該操作可以轉(zhuǎn)化成下面三條機(jī)器指令序列:(1)得到當(dāng)前變量i的值并拷貝到一個(gè)寄存器中(2)將寄存器中的值加1(3)把i的新值寫回到內(nèi)存中

<>臨界區(qū)舉例Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第117頁!

當(dāng)共享資源是一個(gè)復(fù)雜的數(shù)據(jù)結(jié)構(gòu)時(shí),競(jìng)爭(zhēng)狀態(tài)往往會(huì)使該數(shù)據(jù)結(jié)構(gòu)遭到破壞。

對(duì)于這種情況,鎖機(jī)制可以避免競(jìng)爭(zhēng)狀態(tài)正如門鎖和門一樣,門后的房間可想象成一個(gè)臨界區(qū)。

在一個(gè)指定時(shí)間內(nèi),房間里只能有個(gè)一個(gè)內(nèi)核任務(wù)存在,當(dāng)一個(gè)任務(wù)進(jìn)入房間后,它會(huì)鎖住身后的房門;當(dāng)它結(jié)束對(duì)共享數(shù)據(jù)的操作后,就會(huì)走出房間,打開門鎖。如果另一個(gè)任務(wù)在房門上鎖時(shí)來了,那么它就必須等待房間內(nèi)的任務(wù)出來并打開門鎖后,才能進(jìn)入房間。

<>共享隊(duì)列和加鎖Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第118頁!

找出哪些數(shù)據(jù)需要保護(hù)是關(guān)鍵所在

內(nèi)核任務(wù)的局部數(shù)據(jù)僅僅被它本身訪問,顯然不需要保護(hù)

如果數(shù)據(jù)只會(huì)被特定的進(jìn)程訪問,也不需加鎖

大多數(shù)內(nèi)核數(shù)據(jù)結(jié)構(gòu)都需要加鎖:若有其它內(nèi)核任務(wù)可以訪問這些數(shù)據(jù),那么就給這些數(shù)據(jù)加上某種形式的鎖;若任何其它東西能看到它,那么就要鎖住它

<>確定保護(hù)對(duì)象Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第119頁!

加鎖的順序是關(guān)鍵。使用嵌套的鎖時(shí)必須保證以相同的順序獲取鎖,這樣可以阻止致命擁抱類型的死鎖

防止發(fā)生饑餓

不要重復(fù)請(qǐng)求同一個(gè)鎖。

越復(fù)雜的加鎖方案越有可能造成死鎖,因此設(shè)計(jì)應(yīng)力求簡(jiǎn)單

<>死鎖的避免Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第120頁!

為了避免并發(fā),防止競(jìng)爭(zhēng)。內(nèi)核提供了一組同步方法來提供對(duì)共享數(shù)據(jù)的保護(hù)

原子操作自旋鎖信號(hào)量

<>內(nèi)核同步措施Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第121頁!

自旋鎖是專為防止多處理器并發(fā)而引入的一種鎖,它在內(nèi)核中大量應(yīng)用于中斷處理等部分,而對(duì)于單處理器來說,可簡(jiǎn)單采用關(guān)閉中斷的方式防止中斷處理程序的并發(fā)執(zhí)行

自旋鎖最多只能被一個(gè)內(nèi)核任務(wù)持有,若一個(gè)內(nèi)核任務(wù)試圖請(qǐng)求一個(gè)已被持有的自旋鎖,那么這個(gè)任務(wù)就會(huì)一直進(jìn)行忙循環(huán),也就是旋轉(zhuǎn),等待鎖重新可用

<>自旋鎖Linux操作系統(tǒng)原理與應(yīng)用共318頁,您現(xiàn)在瀏覽的是第122頁!

Linux中的信號(hào)量是一種睡眠鎖。若有一個(gè)任務(wù)試圖獲得一個(gè)已被持有的信號(hào)量時(shí),信號(hào)量會(huì)將其推入等待隊(duì)列,然后讓其睡眠。這時(shí)處理器獲得自由而去執(zhí)行其它代碼。當(dāng)持有信號(hào)量的進(jìn)程將信號(hào)量釋放后,在等待隊(duì)列中的一個(gè)任務(wù)將被喚醒,從而便可以獲得這

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論