老熟女激烈的高潮_日韩一级黄色录像_亚洲1区2区3区视频_精品少妇一区二区三区在线播放_国产欧美日产久久_午夜福利精品导航凹凸

重慶分公司,新征程啟航

為企業(yè)提供網(wǎng)站建設(shè)、域名注冊(cè)、服務(wù)器等服務(wù)

Linux系統(tǒng)編程規(guī)范有哪些

這篇文章給大家介紹Linux系統(tǒng)編程規(guī)范有哪些,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。

創(chuàng)新互聯(lián)是一家專注于成都網(wǎng)站建設(shè)、網(wǎng)站制作與策劃設(shè)計(jì),青秀網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)做網(wǎng)站,專注于網(wǎng)站建設(shè)十載,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:青秀等地區(qū)。青秀做網(wǎng)站價(jià)格咨詢:18980820575

1.1 系統(tǒng)調(diào)用概述

系統(tǒng)調(diào)用是操作系統(tǒng)內(nèi)核提供給應(yīng)用程序的基礎(chǔ)接口,需要運(yùn)行在操作系統(tǒng)的核心模式下,以確保有權(quán)限執(zhí)行某些 CPU 特權(quán)指令。

Linux 系統(tǒng)提供了功能非常豐富的系統(tǒng)調(diào)用,涵蓋了文件操作、進(jìn)程控制、內(nèi)存管理、網(wǎng)絡(luò)管理、套接字操作、用戶管理、進(jìn)程間通信等各個(gè)方面。

執(zhí)行如下命令,可列出系統(tǒng)中所有的系統(tǒng)調(diào)用名稱。

man syscalls

Linux 自帶的 man  手冊(cè)對(duì)每個(gè)系統(tǒng)調(diào)用都進(jìn)行了非常詳細(xì)的說(shuō)明,包括函數(shù)功能、傳入的參數(shù)、返回值,以及可能產(chǎn)生的錯(cuò)誤、使用注意事項(xiàng),等等,其完善程度絲毫不亞于微軟的  MSDN。雖然是英文版,但讀起來(lái)比較通俗易懂,每位 Linux 系統(tǒng)開發(fā)者都應(yīng)該習(xí)慣于查看這些文檔。

另外,IBM 文檔庫(kù)里有一份質(zhì)量非常高的《中文版系統(tǒng)調(diào)用列表》,閱讀它會(huì)更輕松。

1.2 系統(tǒng)調(diào)用的兩種調(diào)用方式

我們先看一種方式。

系統(tǒng)調(diào)用由指派的編號(hào)來(lái)標(biāo)識(shí),通過(guò) syscall 函數(shù)以編號(hào)為參數(shù)可直接被調(diào)用。

syscall 函數(shù)原型為:

int syscall(int number, ...);

完整的系統(tǒng)調(diào)用編號(hào)都定義在 sys/syscall.h 的文件中。感興趣的讀者可以自行查看。

顯然,記憶如此多的編號(hào),對(duì)開發(fā)者很不友好。

于是,開發(fā)者多會(huì)選擇第二種方式,即利用 glibc 提供的包裝函數(shù)將這些系統(tǒng)調(diào)用包裝成名字自解釋的函數(shù)。

這個(gè)過(guò)程,包裝函數(shù)并沒有做太多額外工作,主要是檢查參數(shù),將它們拷貝到合適的寄存器中,接著調(diào)用指定標(biāo)號(hào)的系統(tǒng)調(diào)用,之后再根據(jù)結(jié)果設(shè)置  errno,供應(yīng)用程序檢查執(zhí)行結(jié)果,以及其他相關(guān)工作。

兩種調(diào)用方式,在功能上可以認(rèn)為是完全等價(jià)的,但在易讀、易用性上,glibc 包裝函數(shù)則更有優(yōu)勢(shì)。在之后的課程中,我提到某系統(tǒng)調(diào)用,若無(wú)特殊說(shuō)明,指的便是  glibc 包裝函數(shù)。

當(dāng)然,如果包裝函數(shù)無(wú)法滿足某些特殊應(yīng)用場(chǎng)景需求,還可以使用 syscall  函數(shù)直接執(zhí)行系統(tǒng)調(diào)用。不過(guò)這種情況非常少見,到目前為止,我還沒有遇到過(guò)。

1.3 系統(tǒng)調(diào)用的兩種執(zhí)行過(guò)程

1.3.1 基于中斷方式

系統(tǒng)調(diào)用的實(shí)現(xiàn)代碼是內(nèi)核代碼的一部分。執(zhí)行系統(tǒng)調(diào)用代碼,首先需要將系統(tǒng)從用戶模式切換到核心模式。

早期的系統(tǒng)調(diào)用通過(guò)軟中斷實(shí)現(xiàn)模式的切換,而中斷號(hào)屬于系統(tǒng)稀缺資源,不可能為每個(gè)系統(tǒng)調(diào)用都分配一個(gè)中斷號(hào)。

在 Linux 的實(shí)現(xiàn)中,所有的系統(tǒng)調(diào)用共用 128 號(hào)中斷(也就是大名鼎鼎的 int 0x80 ),其對(duì)應(yīng)的中斷處理程序是  system_call,所有的系統(tǒng)調(diào)用都會(huì)轉(zhuǎn)到這個(gè)中斷處理程序中。

接著,system_call 會(huì)根據(jù) EAX 傳入的系統(tǒng)調(diào)用標(biāo)號(hào)跳轉(zhuǎn)并執(zhí)行相應(yīng)的系統(tǒng)調(diào)用程序。如果需要更多的參數(shù),會(huì)依次用 EBX、ECX、EDX、EDI  進(jìn)行傳遞。函數(shù)執(zhí)行完成之后,會(huì)把結(jié)果放到 EAX 中返回給應(yīng)用程序。

由此可知,一次系統(tǒng)調(diào)用便會(huì)觸發(fā)一次完整的中斷處理過(guò)程。在每次中斷處理過(guò)程中,CPU  都會(huì)從系統(tǒng)啟動(dòng)時(shí)初始化好的中斷描述表中,取出該中斷對(duì)應(yīng)的門描述符,并判斷門描述符的種類。

在確認(rèn)門描述符的級(jí)別(DPL)不比中斷指令調(diào)用者的級(jí)別(CPL)低之后,再根據(jù)描述符的內(nèi)容,將中斷處理程序中可能用到的寄存器進(jìn)行壓棧保存。然后,執(zhí)行權(quán)限提升,設(shè)置  CS 和 EIP 寄存器,以使 CPU 跳轉(zhuǎn)到指定的系統(tǒng)調(diào)用的代碼地址,并執(zhí)行目標(biāo)系統(tǒng)調(diào)用。

1.3.2 基于 SYSENTER 指令

再仔細(xì)審視基于中斷方式的系統(tǒng)調(diào)用的執(zhí)行過(guò)程,不難發(fā)現(xiàn),前面很多處理過(guò)程都是固定的,其實(shí)很沒必要,如門描述符級(jí)別檢查、查找中斷處理程序入口,等等。

為了省去這些多余的檢查,Intel 在 Pentium II CPU 中加入了新的 SYSENTER 指令,專門用來(lái)執(zhí)行系統(tǒng)調(diào)用。

該指令會(huì)跳過(guò)前面檢查步驟,直接將 CPU  切換到特權(quán)模式,繼而執(zhí)行系統(tǒng)調(diào)用,同時(shí)還增加了幾個(gè)專用寄存器輔助完成參數(shù)傳遞和上下文保存工作。另外,還相應(yīng)地增加了 SYSEXIT  指令,用來(lái)返回執(zhí)行結(jié)果,并切回用戶模式。

在 Linux 實(shí)現(xiàn)了 SYSENTER 方式的系統(tǒng)調(diào)用之后,就有人用 Pentium III  的機(jī)器對(duì)比測(cè)試了兩種系統(tǒng)調(diào)用的效率。測(cè)試結(jié)果顯示,與中斷方式相比,SYSENTER 在用戶模式下因省掉了級(jí)別檢查類的操作,花費(fèi)的時(shí)間大幅減少了 45%  左右;在核心模式下,因少了一個(gè)寄存器壓棧保存動(dòng)作,所花費(fèi)的時(shí)間也減少了 2% 左右。

目前,基于中斷方式的系統(tǒng)調(diào)用仍然保留著,Linux 啟動(dòng)時(shí)會(huì)自動(dòng)檢測(cè) CPU 是否支持 SYSENTER  指令,從而根據(jù)情況選擇相應(yīng)的系統(tǒng)調(diào)用方式。

1.3.3 SYSENTER 指令誕生故事

介紹完了 SYSENTER 指令的優(yōu)越之處,我們回過(guò)頭再來(lái)聊聊它的由來(lái)。

從 Linux 2.5 內(nèi)核開始,在經(jīng)歷了多方測(cè)試、多次 Patch 之后,SYSENTER 指令才正式被 Linux 2.6 版本支持,且由 Linus  Torvalds 大神親自操刀實(shí)現(xiàn)。

上面提到過(guò),其實(shí)早在 1998 年,SYSENTER 指令就已經(jīng)引入到 Intel Pentium II CPU 中,直到 2002 年才在 Linux  2.5 版本的內(nèi)核中出現(xiàn)。該指令一出現(xiàn),Linux 社區(qū)就開始了激烈討論。

后來(lái) Intel Pentium 4 CPU 發(fā)布了,這款 CPU 在“設(shè)計(jì)上存在的問題,造成 Pentium 4 使用中斷方式執(zhí)行系統(tǒng)調(diào)用比  Pentium 3 以及 AMD Athlon 所耗費(fèi)的 CPU 時(shí)鐘周期多 5~10 倍”,Linus 對(duì)這個(gè)結(jié)果接受不了,于是在 Linux 2.6  內(nèi)核中加入了 SYSENTER 指令,從而實(shí)現(xiàn)了更加高效的系統(tǒng)調(diào)用。

這里總結(jié)下系統(tǒng)調(diào)用的執(zhí)行過(guò)程。進(jìn)程從用戶模式轉(zhuǎn)入核心模式,開始執(zhí)行內(nèi)核中實(shí)現(xiàn)特定功能的代碼段,執(zhí)行完成后再切回用戶模式,并把執(zhí)行結(jié)果返回給調(diào)用進(jìn)程。在  Linux 2.4 版本之前,主要利用中斷方式實(shí)現(xiàn)核心模式的切換;Linux 2.6 及以后版本的內(nèi)核中,可以利用更高效的 SYSENTER 指令實(shí)現(xiàn)。

1.4 系統(tǒng)調(diào)用的標(biāo)準(zhǔn)使用方法

前面提到,本課程所說(shuō)的系統(tǒng)調(diào)用,默認(rèn)是指 glibc  中的包裝函數(shù)。這些函數(shù)會(huì)在執(zhí)行系統(tǒng)調(diào)用前設(shè)置寄存器的狀態(tài),并仔細(xì)檢查輸入?yún)?shù)的有效性。系統(tǒng)調(diào)用執(zhí)行完成后,會(huì)從 EAX 寄存器中獲取內(nèi)核代碼執(zhí)行結(jié)果。

內(nèi)核執(zhí)行系統(tǒng)調(diào)用時(shí),一旦發(fā)生錯(cuò)誤,便將 EAX 設(shè)置為一個(gè)負(fù)整數(shù),包裝函數(shù)隨之將這個(gè)負(fù)數(shù)去掉符號(hào)后,放置到一個(gè)全局的 errno 中,并返回  −1。若沒有發(fā)生錯(cuò)誤,EAX 將被設(shè)置為 0,包裝函數(shù)獲取該值后,并返回 0,表示執(zhí)行成功,此時(shí)無(wú)需再設(shè)置 errno。

綜上,系統(tǒng)調(diào)用的標(biāo)準(zhǔn)使用方法可總結(jié)為:根據(jù)包裝函數(shù)返回值的正負(fù),確定系統(tǒng)調(diào)用是否成功。如果不成功,進(jìn)一步通過(guò) errno  確定出錯(cuò)原因,根據(jù)不同的出錯(cuò)原因,執(zhí)行不同的操作;如果成功,則繼續(xù)執(zhí)行后續(xù)的邏輯。代碼示例如下:

int ret = syscallx(...); if(ret < 0) {  //有錯(cuò)誤了,通過(guò) errno 確定出錯(cuò)的原因,執(zhí)行不同的操作 } else {  //調(diào)用成功,繼續(xù)干活 }

大多數(shù)系統(tǒng)調(diào)用都遵循這一過(guò)程,errno 是一個(gè)整數(shù),可以用 perror 或 strerror 獲得對(duì)應(yīng)的文字描述信息。

不過(guò),也有幾個(gè)特殊的系統(tǒng)調(diào)用,和上述使用方法存在些許差異。比如,其中有個(gè)函數(shù)會(huì)在調(diào)用之前將 errno 重置為 0,調(diào)用后,通過(guò)檢查 errno  判斷執(zhí)行是否成功。此類函數(shù)只有非常少數(shù)的幾個(gè),使用之前,看看幫助頁(yè),就知道如何使用了。

系統(tǒng)調(diào)用的使用規(guī)范就介紹到這里。此時(shí),你可能有個(gè)疑問,每個(gè)系統(tǒng)調(diào)用失敗后都會(huì)設(shè)置 errno,如果在多線程程序中,不同線程中的系統(tǒng)調(diào)用設(shè)置的 errno  會(huì)不會(huì)互相干擾呢?

如果 errno 是一個(gè)全局變量,答案是肯定的。如果真是這樣的話,那系統(tǒng)調(diào)用的局限性也就太大了,總不能在每個(gè)系統(tǒng)調(diào)用之前都加鎖保護(hù)吧。優(yōu)秀的 Linux  肯定不會(huì)這么弱,那么,這個(gè) errno 的問題又是怎么解決的呢?

1.5 errno 的多線程問題

根據(jù) man 手冊(cè),要使用 errno,首先需要包含 errno.h 這個(gè)頭文件。我們先看看 errno.h 里面有什么東西。

vim /usr/include/errno.h

執(zhí)行以上代碼,會(huì)發(fā)現(xiàn)該文件中有這樣幾行關(guān)鍵內(nèi)容:

#include  ....... #ifndef errno extern int errno; #endif

根據(jù)官方提供的代碼注釋,bits/errno.h 中應(yīng)該有一個(gè) errno 的宏定義。如果沒有,則會(huì)在外部變量中尋找一個(gè)名為 errno  的整數(shù),它自然也就成了全局整數(shù)。否則,這個(gè) errno 只是一個(gè) per-thread 變量,每個(gè)線程都會(huì)拷貝一份。

關(guān)于 per-thread 變量更詳細(xì)的信息,我們會(huì)在后面的課程中介紹。現(xiàn)在,你只需知道,這個(gè)  errno,每個(gè)線程都會(huì)獨(dú)立拷貝一份,所以在多線程程序中使用它是不會(huì)相互影響的。

1.5.1 實(shí)現(xiàn)原理

具體是怎么做到的呢?我們可以再打開 bits/errno.h 看一眼。

 # ifndef __ASSEMBLER__ extern int *__errno_location (void) __THROW __attribute__ ((__const__)); # if !defined _LIBC || defined _LIBC_REENTRANT # define errno (*__errno_location ()) # endif # endif

原來(lái),當(dāng) libc 被定義為可重入時(shí),errno 就會(huì)被定義成一個(gè)宏,該宏調(diào)用外部 __errno_location 函數(shù)返回的內(nèi)存地址中所存儲(chǔ)的值。在  GCC 源碼中,我們還發(fā)現(xiàn)一個(gè)測(cè)試用例中定義了 __errno_location 函數(shù)的 Stub,是這樣寫的:

extern __thread int __libc_errno __attribute__ ((tls_model ("initial-exec"))); int * __errno_location (void) {  return &__libc_errno; }

這一簡(jiǎn)單的測(cè)試用例充分展現(xiàn)了 errno 的實(shí)現(xiàn)原理。errno 被定義為 per-thread(用 __thread 標(biāo)識(shí)的線程局部存儲(chǔ)類型)變量  __libc_errno,之后 __errno_location 函數(shù)返回了這個(gè)線程局部變量的地址。所以,在每個(gè)線程中獲取和設(shè)置 errno  的時(shí)候,操作的是本線程內(nèi)的一個(gè)變量,不會(huì)與其他線程相互干擾。

至于 __thread 這個(gè)關(guān)鍵字,需要在很“嚴(yán)苛”的條件下才能生效——需要 Linux 2.6 以上內(nèi)核、pthreads 庫(kù)、GCC 3.3  或更高版本的支持。不過(guò),放到今天,這些條件已成為標(biāo)配,也就不算什么了。

1.5.2 注意事項(xiàng)

上面只是解釋了在多線程中使用系統(tǒng)調(diào)用時(shí),errno 不會(huì)發(fā)生沖突問題,但并不是說(shuō)所有的系統(tǒng)調(diào)用都可以放心大膽地在多線程程序中使用。

有一些系統(tǒng)調(diào)用,標(biāo)準(zhǔn)中并沒有規(guī)定它們的實(shí)現(xiàn)必須是多線程安全的(或者說(shuō)可重入的,后面的課程中再詳細(xì)解釋)。由于歷史原因和實(shí)現(xiàn)原理上的限制,有些函數(shù)的實(shí)現(xiàn)并不是線程安全的,比如  system()。某些 glibc 函數(shù)也是一樣,比如 strerror 函數(shù),其內(nèi)部使用一塊靜態(tài)存儲(chǔ)區(qū)存放 errno  描述性信息,最近的一次調(diào)用會(huì)覆蓋上一次調(diào)用的內(nèi)容。

關(guān)于Linux系統(tǒng)編程規(guī)范有哪些就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。


文章名稱:Linux系統(tǒng)編程規(guī)范有哪些
路徑分享:http://www.xueling.net.cn/article/pggoeo.html

其他資訊

在線咨詢
服務(wù)熱線
服務(wù)熱線:028-86922220
TOP
主站蜘蛛池模板: 久草av网| 14表妺好紧没带套在线播放 | 一区二区三区国产在线观看 | 在线观看免费人成视频播放 | 成人性生活大片100部 | 99探花在线观看 | 爱爱视频一区 | 精品国产免费人成网站 | heyzo无码中文字幕在线 | 欧美级特黄AAAAAA片 | 国产夫妻自拍小视频 | 国产精品自在线拍国产手青青机版 | 少妇人妻久久无码专区 | 精品一区二区日韩 | 快色视频 | 麻豆91在线播放免费 | 久久精品天堂 | 日本乱偷人妻中文字幕在线 | 妃子涨奶和侍卫h | 人妻熟妇AV水蜜桃一区二区三区 | 在线观看视频在线高清免费播放网站 | A片粗大的内捧猛烈进出AVV | 精品无码免费专区毛片 | yp最新网站入口 | 免费看含羞草AV片成人 | 女人自慰喷水高清播放 | 久久久久久69 | 少妇伦子伦精品无码 | 国产产一区二区三区久久毛片国语 | 古代级a毛片免费观看 | 亚洲一区精品视频在线观看 | 国产成人AV在线影院 | 日本黄色一级片视频 | 日本少妇又色又爽又高潮看你 | 美国三级影院 | av成人毛片 | 国产成人久久精品二三区无码 | 欧美性xxxx69| 农村妇女一级片 | 亚洲国产精品成人精品无码区 | 亚洲免费网址 |