<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 《ARM與Linux些許問題》第四章:ARM平臺系統(tǒng)調(diào)用原理分析

          《ARM與Linux些許問題》第四章:ARM平臺系統(tǒng)調(diào)用原理分析

          作者: 時間:2016-11-09 來源:網(wǎng)絡(luò) 收藏
          本文基于mstar801平臺Linux2.6.35.11版本。

          首先說明:系統(tǒng)調(diào)用不會導(dǎo)致進(jìn)程上下文切換。

          本文引用地址:http://www.ex-cimer.com/article/201611/317769.htm

          一、介紹系統(tǒng)調(diào)用——Linux用戶空間主動進(jìn)入內(nèi)核空間的唯一方法

          1.系統(tǒng)調(diào)用是操作系統(tǒng)提供給用戶程序調(diào)用的一組“特殊”接口;用戶程序可以通過這組“特殊”接口來獲得操作系統(tǒng)內(nèi)核提供的服務(wù)。

          從邏輯上來說,系統(tǒng)調(diào)用可被看成是一個內(nèi)核與用戶空間程序交互的接口;把用戶進(jìn)程的請求傳達(dá)給內(nèi)核,待內(nèi)核把請求處理完畢后再將處理結(jié)果送回給用戶空間。

          2.系統(tǒng)調(diào)用按照功能邏輯大致可分為“進(jìn)程控制”、“文件系統(tǒng)控制”、“系統(tǒng)控制”、“存儲管理”、“網(wǎng)絡(luò)管理”、“socket控制”、“用戶管理”和“進(jìn)程間通信”幾類。

          3.內(nèi)核接口:kernel2.6.35.11/arch/arm/include/asm/unistd.h

          二、系統(tǒng)調(diào)用的主要用途

          1.控制硬件——系統(tǒng)調(diào)用往往作為硬件資源和用戶空間的抽象接口,比如讀寫文件時用到的write/read調(diào)用。

          2.設(shè)置系統(tǒng)狀態(tài)或讀取內(nèi)核數(shù)據(jù)——因?yàn)橄到y(tǒng)調(diào)用是用戶空間和內(nèi)核的唯一通訊手段,所以用戶設(shè)置系統(tǒng)狀態(tài)、比如開/關(guān)某項(xiàng)內(nèi)核服務(wù)(設(shè)置某個內(nèi)核變量)或讀取內(nèi)核數(shù)據(jù)都必須通過系統(tǒng)調(diào)用。比如getpid、getpriority、setpriority和sethostname等。

          3.進(jìn)程管理——系統(tǒng)調(diào)用接口用來保證系統(tǒng)中進(jìn)程能以多任務(wù)在虛擬內(nèi)存環(huán)境下運(yùn)行。比如fork、clone、execve和exit等。

          三、內(nèi)核函數(shù)和系統(tǒng)調(diào)用、用戶編程接口(API)、系統(tǒng)命令的關(guān)系

          1.系統(tǒng)調(diào)用并非直接和程序員或系統(tǒng)管理員打交道,它僅僅是一個通過軟中斷機(jī)制向內(nèi)核提交請求、獲取內(nèi)核服務(wù)的接口。而在實(shí)際使用中程序員調(diào)用的多是用戶編程接口——api,而管理員使用的則多是系統(tǒng)命令。

          2.用戶編程接口(API)其實(shí)是一個函數(shù)定義,說明了如何獲得一個給定的服務(wù),比如read()、malloc()、free()、abs()等。

          它有可能和系統(tǒng)調(diào)用形式一致,比如read()接口就和read系統(tǒng)調(diào)用一一對應(yīng);

          往往會出現(xiàn)幾種不同的API內(nèi)部用到同一個系統(tǒng)調(diào)用,比如malloc()、free()內(nèi)部利用brk()系統(tǒng)調(diào)用來擴(kuò)大或縮小進(jìn)程的堆;

          或一個API利用了好幾個系統(tǒng)調(diào)用組合來完成任務(wù);

          更有些API甚至不需要任何系統(tǒng)調(diào)用,因?yàn)樗恍枰獌?nèi)核服務(wù)、如計算整數(shù)絕對值的abs()接口。

          Linux系統(tǒng)中這些API主要是通過C庫(libc)實(shí)現(xiàn)的;它除了定義的一些標(biāo)準(zhǔn)的C函數(shù)外,一個重要的任務(wù)是提供了一套封裝例程、將系統(tǒng)調(diào)用在用戶空間包裝后供用戶編程使用。

          說明:上述封裝并非必須;如果你愿意直接調(diào)用,Linux提供了一個syscall()的系統(tǒng)調(diào)用函數(shù)來實(shí)現(xiàn)調(diào)用。

          3.系統(tǒng)命令相對編程接口更高了一層,它是內(nèi)部引用API的可執(zhí)行程序,比如我們常用的系統(tǒng)命令ls、hostname等。

          三、內(nèi)核函數(shù)和系統(tǒng)調(diào)用的關(guān)系

          內(nèi)核函數(shù)沒有想像中那么復(fù)雜;它們和普通函數(shù)很像、只不過在內(nèi)核實(shí)現(xiàn),因此要滿足一些內(nèi)核編程的要求。

          系統(tǒng)調(diào)用是一層用戶進(jìn)入內(nèi)核的接口,它本身并非內(nèi)核函數(shù);進(jìn)入內(nèi)核后,不同的系統(tǒng)調(diào)用會找到對應(yīng)到各自的內(nèi)核函數(shù)——專業(yè)術(shù)語叫:系統(tǒng)調(diào)用服務(wù)例程。

          總結(jié):從用戶角度向內(nèi)核看;依次是系統(tǒng)命令、編程接口、系統(tǒng)調(diào)用和內(nèi)核函數(shù)。
          四、系統(tǒng)調(diào)用的實(shí)現(xiàn)

          系統(tǒng)調(diào)用利用了ARM體系結(jié)構(gòu)中的軟件中斷,軟件中斷和我們常說的中斷(硬件中斷)不同之處在于———它是通過軟件指令觸發(fā)而并非外設(shè),也就是說由編程人員發(fā)出的一種異常;具體地講就是調(diào)用SWI匯編指令(x86上int $0x80),這條匯編指令將產(chǎn)生向量為128的編程異常,ARM從用戶模式切入管理模式、并強(qiáng)制R15-PC(程序計數(shù)器)為0x0000 0008,Linux從用戶態(tài)進(jìn)入內(nèi)核態(tài)。見:《ARM與Linux些許問題》第一章:ARM工作模式

          之所以系統(tǒng)調(diào)用需要借助異常實(shí)現(xiàn);是因?yàn)楫?dāng)用戶態(tài)的進(jìn)程調(diào)用一個系統(tǒng)調(diào)用時,CPU便被切換到內(nèi)核態(tài)執(zhí)行內(nèi)核函數(shù)。我們前邊分析ARM體系結(jié)構(gòu)部分已經(jīng)講過進(jìn)入內(nèi)核態(tài)——ARM高特權(quán)模式,必須經(jīng)過系統(tǒng)的門機(jī)制——異常(SWI匯編指令(x86上int $0x80等);其他異常用戶空間無法利用,都是由內(nèi)核使用的。)。

          1.SWI匯編指令(x86上int $0x80)指令的目的是產(chǎn)生一個編號為128的編程異常,這個編程異常對應(yīng)中斷描述符表IDT中的第128項(xiàng)——也就是對應(yīng)的系統(tǒng)門描述符。門描述符中含有一個預(yù)設(shè)的內(nèi)核空間地址,它指向了系統(tǒng)調(diào)用處理程序:vector_SWI()(x86上system_call())。注意:不是系統(tǒng)調(diào)用服務(wù)程序本身。

          即:系統(tǒng)命令——>用戶編程API——>系統(tǒng)調(diào)用(調(diào)用SWI匯編指令異常)——>系統(tǒng)調(diào)用處理函數(shù)(vector_SWI)——>具體的系統(tǒng)調(diào)用服務(wù)程序。其中藍(lán)色部分是內(nèi)核態(tài)函數(shù)。

          2.所有的用戶空間系統(tǒng)調(diào)用函數(shù)都是通過調(diào)用SWI匯編指令(x86上int $0x80)異常、進(jìn)入內(nèi)核態(tài),此時、ARM默認(rèn)從某一固定地址執(zhí)行程序(vector_SWI()(x86上system_call())的地址)。vector_SWI()(x86上system_call())這個內(nèi)核函數(shù)又怎樣分發(fā)這些系統(tǒng)調(diào)用到各自的內(nèi)核服務(wù)程序中呢?Linux為每個系統(tǒng)調(diào)用都進(jìn)行了編號(0——_NR_syscall);同時在內(nèi)核中保存一張系統(tǒng)調(diào)用表,該表中保存了系統(tǒng)調(diào)用編號和其對應(yīng)的服務(wù)例程。因此,在系統(tǒng)調(diào)用通過門陷入內(nèi)核前,需要把系統(tǒng)調(diào)用號一并傳入內(nèi)核。這個傳遞工作是通過把系統(tǒng)調(diào)用號裝入相應(yīng)寄存器實(shí)現(xiàn)的。

          有了如上的分析:系統(tǒng)調(diào)用處理程序vector_SWI()(x86上system_call())一旦運(yùn)行;就可以從相應(yīng)寄存器中得到數(shù)據(jù),然后再去系統(tǒng)調(diào)用表中尋找相應(yīng)的服務(wù)例程了。

          注意:除了系統(tǒng)調(diào)用號之外,有的系統(tǒng)調(diào)用還需要傳遞一些參數(shù)給內(nèi)核;這是Linux在vector_SWI()(x86上system_call())調(diào)用時將參數(shù)等值傳入其他寄存器。

          內(nèi)核系統(tǒng)服務(wù)例程結(jié)束時,system_call()從相應(yīng)寄存器中獲得系統(tǒng)調(diào)用返回值,并把這個返回值放在曾保存用戶態(tài)相應(yīng)寄存器棧單元的那個位置;然后跳轉(zhuǎn)到ret_from_sys_call(),終止系統(tǒng)調(diào)用處理程序的執(zhí)行。

          ====================================================================================================================================

          五、主要路徑

          1.用戶空間:libc庫沒有研究代碼,大體機(jī)制如下——

          調(diào)用SWI匯編指令(x86上int $0x80))軟中斷進(jìn)入內(nèi)核,并傳入中斷向量號

          相關(guān)中斷向量號arm-2010.09/arm-none-linux-gnueabi/libc/usr/include/bits/syscall.h

          #define SYS_getuid __NR_getuid

          2.內(nèi)核空間:ARM中系統(tǒng)調(diào)用號定義路徑:kernel2.6.35.11/arch/arm/include/asm/unistd.h
          #define __NR_getuid (__NR_SYSCALL_BASE+ 24)

          異常進(jìn)入內(nèi)核空間函數(shù)路徑:kernel2.6.35.11/arch/arm/kernel/entry-common.s

          默認(rèn)執(zhí)行vector_SWI(x86上system_call())函數(shù)

          ARM中系統(tǒng)調(diào)用表定義路徑:kernel2.6.35.11/arch/arm/kernel/calls.S

          CALL(sys_getuid) //第24個,要與前面unistd中對應(yīng)

          ARM中系統(tǒng)調(diào)用服務(wù)程序的聲明路徑:kernel2.6.35.11/include/linux/syscalls.h

          asmlinkage long sys_getuid(void);

          ====================================================================================================================================

          x86平臺相關(guān)路徑(內(nèi)核):

          系統(tǒng)調(diào)用號路徑——kernel2.6.35.11/arch/x86/include/asm/unistd.h

          system_call()函數(shù)路徑——kernel2.6.35.11/arch/x86/kernel/entry.S

          系統(tǒng)調(diào)用表路徑——kernel2.6.35.11/arch/x86/kernel/syscall_table.S或直接在entry.S中定義


          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();