今天就跟大家聊聊有關(guān)系統(tǒng)調(diào)用有什么目的,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
道外ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場(chǎng)景,ssl證書未來市場(chǎng)廣闊!成為成都創(chuàng)新互聯(lián)的ssl證書銷售渠道,可以享受市場(chǎng)價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:028-86922220(備注:SSL證書合作)期待與您的合作!
系統(tǒng)調(diào)用的目的是:請(qǐng)求系統(tǒng)服務(wù)。操作系統(tǒng)不允許用戶直接操作各種硬件資源,因此用戶程序只能通過系統(tǒng)調(diào)用的方式來請(qǐng)求內(nèi)核為其服務(wù),間接地使用各種資源。
由操作系統(tǒng)提供的功能,通常應(yīng)用程序本身是無法實(shí)現(xiàn)的。例如對(duì)文件進(jìn)行操作,應(yīng)用程序必需通過系統(tǒng)調(diào)用才能做到,因?yàn)橹挥胁僮飨到y(tǒng)才具有直接管理外圍設(shè)備的權(quán)限。又如進(jìn)程或線程間的同步互斥操作,也必需經(jīng)由操作系統(tǒng)對(duì)內(nèi)核變量進(jìn)行維護(hù)才能完成。
從下到上看一個(gè)完整的計(jì)算機(jī)系統(tǒng):物理硬件->OS內(nèi)核->OS服務(wù)->應(yīng)用程序。這里的OS內(nèi)核起到了“承上啟下”的關(guān)鍵作用,向下管理物理硬件,向上為操作系統(tǒng)服務(wù)和應(yīng)用程序提供接口,這里的接口就是系統(tǒng)調(diào)用了。
應(yīng)用程序的進(jìn)程通常在user模式下運(yùn)行,當(dāng)它調(diào)用一個(gè)系統(tǒng)調(diào)用時(shí),進(jìn)程進(jìn)入kernel模式,執(zhí)行的是kernel內(nèi)部的代碼,從而具有執(zhí)行特權(quán)指令的權(quán)限,完成特定的功能。換句話說,系統(tǒng)調(diào)用是應(yīng)用程序主動(dòng)進(jìn)入操作系統(tǒng)內(nèi)核的入口。
顧名思義是把函數(shù)放到庫里,是把一些常用到的函數(shù)編完放到一個(gè)文件里,供別人用。別人用的時(shí)候把所在的文件名用#include<>加到里面就可以了,一般放到lib文件里。
庫函數(shù)主要由兩方面提供:一是操作系統(tǒng)提供的;另一類是由第三方提供的。
系統(tǒng)提供的這些函數(shù)把系統(tǒng)調(diào)用進(jìn)行封裝或者組合,可以實(shí)現(xiàn)更多的功能,這樣的庫函數(shù)能夠?qū)崿F(xiàn)一些對(duì)于內(nèi)核來說比較復(fù)雜的操作。比如read函數(shù)根據(jù)參數(shù),直接就能讀文件,而背后隱藏的文件比如在那個(gè)磁道,那個(gè)扇區(qū),加載到那個(gè)內(nèi)存,是程序員不必關(guān)心的問題。這些操作里面也包含了系統(tǒng)調(diào)用。比如write()這個(gè)系統(tǒng)函數(shù),會(huì)調(diào)用同名的系統(tǒng)調(diào)用,來完成寫入操作。
對(duì)于第三方庫,其實(shí)和系統(tǒng)庫一樣,只是他直接利用系統(tǒng)調(diào)用的可能性要小一些,而是系統(tǒng)提供的API接口來是實(shí)現(xiàn)。比如printf,實(shí)際上調(diào)用了write()這個(gè)系統(tǒng)函數(shù)。 第三方庫函數(shù)大部分是對(duì)系統(tǒng)函數(shù)的封裝。
系統(tǒng)調(diào)用和庫函數(shù)的聯(lián)系:
事實(shí)上,系統(tǒng)調(diào)用所提供給用戶的是直接而純碎的高級(jí)服務(wù),如果想要更加人性化,具有更符合特定情況的功能,那么就要我們用戶自己定義,因此衍生了庫函數(shù),它把部分系統(tǒng)調(diào)用包裝起來。比如當(dāng)我們要用C語言打印一句話的時(shí)候,如果沒有用到庫函數(shù)printf,那么我們就需要自己實(shí)現(xiàn)就需要調(diào)用putc()和write()等這樣一些系統(tǒng)函數(shù)。顯得比較麻煩,所以系統(tǒng)調(diào)用是為了方便使用操作系統(tǒng)的接口,而庫函數(shù)則是為了人們編程的方便。
例如,在Linux操作系統(tǒng)下,C語言的庫函數(shù)printf,實(shí)際上使用了write系統(tǒng)調(diào)用;而庫函數(shù)strcpy(字符串拷貝)卻沒有使用任何系統(tǒng)調(diào)用。另外,一個(gè)系統(tǒng)的系統(tǒng)調(diào)用接口通常是能夠完成所有必需功能的最小集合,可能存在多個(gè)庫函數(shù)對(duì)同一個(gè)系統(tǒng)調(diào)用進(jìn)行封裝。例如,在Linux中,malloc、calloc和free三個(gè)庫函數(shù)底層都是調(diào)用brk系統(tǒng)調(diào)用完成的。
應(yīng)用程序、庫函數(shù)和系統(tǒng)調(diào)用的關(guān)系如下圖所示:
系統(tǒng)調(diào)用和庫函數(shù)的區(qū)別:
庫函數(shù)的調(diào)用是語言或者應(yīng)用程序的一部分,而系統(tǒng)調(diào)用則是操作系統(tǒng)的一部分。
系統(tǒng)調(diào)用是應(yīng)用程序與內(nèi)核交互的接口。人們?cè)陂L(zhǎng)期的編程中發(fā)現(xiàn)使用系統(tǒng)函數(shù)有個(gè)重大的缺點(diǎn),那就是程序的移植性。例如linux提供的系統(tǒng)調(diào)用的函數(shù)和windows就不一樣。
庫函數(shù)調(diào)用則是面向應(yīng)用開發(fā)的,相當(dāng)于應(yīng)用程序的api,采用這樣的方式有很多原因:
二、CPU的內(nèi)核模式和用戶模式
通常,處理器設(shè)有兩種模式:“用戶模式”與“內(nèi)核模式”,通過一個(gè)標(biāo)簽位來鑒別當(dāng)前正處于什么模式。內(nèi)核模式可以運(yùn)行所有指令,包括特權(quán)指令(主要是一些硬件管理的指令,例如修改基址寄存器內(nèi)容的指令) ,而用戶模式不能執(zhí)行特權(quán)指令。這樣的設(shè)計(jì)主要為了安全問題,即由操作系統(tǒng)負(fù)責(zé)管理硬件,避免上層應(yīng)用因錯(cuò)誤設(shè)計(jì)而導(dǎo)致硬件問題。
既然只有操作系統(tǒng)能直接操作硬件,操作系統(tǒng)有必要提供接口來為應(yīng)用程序提供使用硬件功能的入口,這些接口就被稱為系統(tǒng)調(diào)用。
當(dāng)操作系統(tǒng)接收到系統(tǒng)調(diào)用請(qǐng)求后,會(huì)讓處理器進(jìn)入內(nèi)核模式,從而執(zhí)行諸如I/O操作,修改基址寄存器內(nèi)容等指令,而當(dāng)處理完系統(tǒng)調(diào)用內(nèi)容后,操作系統(tǒng)會(huì)讓處理器返回用戶模式,來執(zhí)行用戶代碼。
對(duì)應(yīng)CPU的內(nèi)核模式和用戶模式,進(jìn)程運(yùn)行的狀態(tài)分為管態(tài)(核心態(tài))和目態(tài)(用戶態(tài))。具體請(qǐng)看文章:操作系統(tǒng)--用戶態(tài)和核心態(tài)
中斷(Interrupt)通常是指在CPU內(nèi)部或外部發(fā)生了某個(gè)待處理的事件,從而CPU必需改變當(dāng)前指令的執(zhí)行順序去處理這類事件。在介紹中斷和系統(tǒng)調(diào)用的關(guān)系之前,下面先把中斷做一個(gè)分類。
中斷可以大體分為兩大類:
Asynchronous interrupts(外中斷): 由CPU外部的其它硬件產(chǎn)生,說這類中斷是異步的,意思是中斷信號(hào)可以在任意時(shí)間發(fā)射,與CPU本身的時(shí)鐘節(jié)拍沒有關(guān)系。如時(shí)鐘中斷,硬盤讀寫服務(wù)請(qǐng)求中斷等。
Synchronous interrupts(內(nèi)中斷/異常):在CPU內(nèi)部產(chǎn)生,說這類中斷是同步的,意思是中斷信號(hào)的發(fā)射時(shí)間一定在當(dāng)前指令執(zhí)行結(jié)束之后。一般來自CPU的內(nèi)部事件或程序執(zhí)行中的事件,如非法操作碼、地址越界、浮點(diǎn)溢出等。
Synchronous interrupts (異常)又分為以下若干類:
Processor-detected exceptions:處理器在執(zhí)行指令時(shí)檢測(cè)到的中斷,如除零操作。
Faults:發(fā)生了某個(gè)異常條件,但異常條件被消除后,原來的程序流程可以繼續(xù)執(zhí)行而不受任何影響,如缺頁異常。注意觸發(fā)中斷的指令會(huì)被重新執(zhí)行。
Traps:由陷入指令引起的中斷,通常用于程序調(diào)試。
Aborts:CPU內(nèi)部有重要錯(cuò)誤發(fā)生,例如硬件錯(cuò)誤或系統(tǒng)表值出現(xiàn)錯(cuò)誤。一旦這種中斷發(fā)生,錯(cuò)誤將不可恢復(fù),只能將當(dāng)前進(jìn)程終止。
Programmed exceptions:也稱為 software interrupts (軟中斷),由程序員的代碼主動(dòng)發(fā)起的中斷,用來實(shí)現(xiàn)系統(tǒng)調(diào)用。如在Linux中,就是用int 0x80
指令實(shí)現(xiàn)系統(tǒng)調(diào)用。
至此,我們發(fā)現(xiàn)了中斷與系統(tǒng)調(diào)用的關(guān)系:系統(tǒng)調(diào)用是一種特殊的中斷類型(軟中斷)。
五、內(nèi)核對(duì)于系統(tǒng)調(diào)用的處理
在x86的機(jī)器中,用一個(gè)8bit的數(shù)字(0~255)來區(qū)分各種中斷,這個(gè)數(shù)字被稱為中斷向量(vector)。其中一個(gè)中斷向量,即128 (0x80),專門被用于執(zhí)行系統(tǒng)調(diào)用。
在Linux系統(tǒng)中,存有一個(gè)系統(tǒng)表,叫做Interrupt DescriptorTable,簡(jiǎn)稱IDT。IDT表共有256項(xiàng),存放了從中斷向量到相應(yīng)處理例程(interrupt or exceptionhandler)的映射關(guān)系。當(dāng)某個(gè)中斷發(fā)生時(shí),CPU從IDT表中查找到相應(yīng)的處理例程的地址來執(zhí)行。
系統(tǒng)調(diào)用的處理例程在IDT表中占有一項(xiàng)。這一項(xiàng)是在trap_init函數(shù)中被初始化的,如下:set_system_gate(SYSCALL_VECTOR,&system_call);
。如前所述,上面代碼中的SYSCALL_VECTOR的值是128。
當(dāng)系統(tǒng)調(diào)用發(fā)生時(shí),通過中斷機(jī)制,系統(tǒng)調(diào)用例程system_call被調(diào)用。它的執(zhí)行過程大概分為4個(gè)步驟:
1、從寄存器中取出系統(tǒng)調(diào)用號(hào)和輸入?yún)?shù),然后將這些寄存器的值壓入kernel棧中。根據(jù)系統(tǒng)調(diào)用號(hào)查找系統(tǒng)調(diào)用分派表(system call dispatch table),找到系統(tǒng)調(diào)用服務(wù)例程(一個(gè)內(nèi)核函數(shù))。
2、調(diào)用查到的系統(tǒng)調(diào)用服務(wù)例程。
3、將系統(tǒng)調(diào)用服務(wù)例程的返回值出棧,重新保存在寄存器中。
上面描述的系統(tǒng)調(diào)用例程system_call在kernel空間中執(zhí)行。在執(zhí)行前,系統(tǒng)調(diào)用號(hào)和輸入?yún)?shù)已經(jīng)存入了寄存器,這個(gè)存入過程由user空間的代碼完成。實(shí)際上,如同第一節(jié)所講,每個(gè)真正的系統(tǒng)調(diào)用基本上都有一個(gè)封裝它的庫函數(shù),一般是在這個(gè)庫函數(shù)中完成系統(tǒng)調(diào)用號(hào)和輸入?yún)?shù)的保存動(dòng)作。當(dāng)系統(tǒng)調(diào)用例程system_call執(zhí)行完畢后,返回值通過寄存器再傳回user空間的庫函數(shù)。
看完上述內(nèi)容,你們對(duì)系統(tǒng)調(diào)用有什么目的有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。