linux系统调用理解之摘录(2)
原文博客?http://blog.csdn.net/gatieme/article/details/50779184
Linux系統(tǒng)調(diào)用的實(shí)現(xiàn)機(jī)制分析
本文介紹了系統(tǒng)調(diào)用的一些細(xì)節(jié)。
首先,分析了系統(tǒng)調(diào)用的意義,他們與庫(kù)函數(shù)和應(yīng)用程序接口的關(guān)系。
然后,我們分析內(nèi)核如何實(shí)現(xiàn)系統(tǒng)調(diào)用,以及執(zhí)行系統(tǒng)調(diào)用的連鎖反應(yīng):
陷入內(nèi)核——>傳遞系統(tǒng)調(diào)用號(hào)和外部輸入?yún)?shù)——>執(zhí)行對(duì)應(yīng)的系統(tǒng)調(diào)用函數(shù)——>把返回值帶回用戶(hù)空間。
最后,分析如何增加系統(tǒng)調(diào)用,并提供從用戶(hù)空間訪問(wèn)系統(tǒng)調(diào)用的例子;
1.系統(tǒng)調(diào)用過(guò)的意義
Linux內(nèi)核中設(shè)置了一組用于實(shí)現(xiàn)系統(tǒng)服務(wù)的子程序,這些程序成為系統(tǒng)調(diào)用(程序)。注意:請(qǐng)自行根據(jù)上下文理解“系統(tǒng)調(diào)用”指的是一種操作或是具體的子程序。
系統(tǒng)調(diào)用和普通函數(shù)調(diào)用非常類(lèi)似,只是系統(tǒng)調(diào)用(這里指的是子程序)是由操作系統(tǒng)核心提供,運(yùn)行在內(nèi)核態(tài),而普通的函數(shù)調(diào)用由用由函數(shù)庫(kù)或用戶(hù)自己提供,運(yùn)行在用戶(hù)態(tài)。
一般,進(jìn)程是不能訪問(wèn)內(nèi)核的:不能訪問(wèn)內(nèi)核空間,也不能調(diào)用內(nèi)核函數(shù)。這是由CPU硬件決定的(這就是為什么它被稱(chēng)為“保護(hù)模式”)。為了和用戶(hù)空間上的進(jìn)程進(jìn)行交互,內(nèi)核提供了一組接口,即系統(tǒng)調(diào)用。通過(guò)接口,應(yīng)用程序可以訪問(wèn)硬件設(shè)備和其他操作系統(tǒng)資源。
系統(tǒng)調(diào)用相當(dāng)于在用戶(hù)空間和硬件設(shè)備之間添加了一個(gè)中間層。它的主要作用有三個(gè):
(1)為用戶(hù)空間提供一個(gè)統(tǒng)一的硬件的抽象接口。比如,當(dāng)需要讀取文件的時(shí)候,應(yīng)用程序就可以不去管磁盤(pán)類(lèi)型和介質(zhì),甚至不用管文件所在的文件系統(tǒng)是哪種類(lèi)型,直接通過(guò)接口就能達(dá)到讀文件的目的。
(2)系統(tǒng)調(diào)用保證了系統(tǒng)的穩(wěn)定和安全。作為硬件設(shè)備和應(yīng)用程序之間的中間人,內(nèi)核可以基于權(quán)限和其他一些規(guī)則,對(duì)需要進(jìn)行的用戶(hù)程序請(qǐng)求進(jìn)行裁決。比如,這樣可以避免應(yīng)用程序不正確地使用硬件設(shè)備,或是竊取其他進(jìn)程的而資源,或是做出危害系統(tǒng)的事情。
(3)每個(gè)進(jìn)程都運(yùn)行在虛擬系統(tǒng)中,而在用戶(hù)空間和系統(tǒng)的其他部分之間增加一層公共接口,也是出于這種考慮。如果應(yīng)用程序可以隨意訪問(wèn)硬件而內(nèi)核又對(duì)此一無(wú)所知的話(huà),那就沒(méi)法實(shí)現(xiàn)多任務(wù)和虛擬內(nèi)存。
(迷糊??)
在Linux中,系統(tǒng)調(diào)用時(shí)用戶(hù)空間訪問(wèn)內(nèi)核的唯一手段;除異常和中斷外,系統(tǒng)調(diào)用時(shí)內(nèi)核唯一的合法入口。
2.API/POSIX/C庫(kù)的關(guān)系
一般情況下,應(yīng)用程序通過(guò)應(yīng)用程序接口(API)而不是使用syscall來(lái)實(shí)現(xiàn)系統(tǒng)調(diào)用。
這點(diǎn)很重要,因?yàn)閼?yīng)用程序使用API接口實(shí)際上并不需要和內(nèi)核提供的系統(tǒng)調(diào)用一一對(duì)應(yīng)。一個(gè)API可以通過(guò)一個(gè)系統(tǒng)調(diào)用實(shí)現(xiàn),也可以通過(guò)使用多個(gè)系統(tǒng)調(diào)用來(lái)實(shí)現(xiàn),甚至不適用任何系統(tǒng)調(diào)用也是可以的。實(shí)際上,API可以在各種不同的操作系統(tǒng)上實(shí)現(xiàn),給應(yīng)用程序提供完全一樣的接口,但是在不同系統(tǒng)上,他們的內(nèi)部實(shí)現(xiàn)可能是不同的(比如通過(guò) ifdef 來(lái)區(qū)分)。
在UNIX中,最流行的API是基于POSIX標(biāo)準(zhǔn),其目標(biāo)是提供一套基于unix的可移植操作系統(tǒng)標(biāo)準(zhǔn)。
POSIX是說(shuō)明API和系統(tǒng)調(diào)用之間關(guān)系的一個(gè)極好的例子。在大多數(shù)Unix系統(tǒng)上,根據(jù)POSIX標(biāo)準(zhǔn)定義的API函數(shù)和系統(tǒng)調(diào)用之間有直接的關(guān)系。
Linux的系統(tǒng)調(diào)用與大多數(shù)Unix系統(tǒng)一樣,作為C庫(kù)的一部分提供,如下圖所示。C庫(kù)實(shí)現(xiàn)了Unix系統(tǒng)的主要API,包括標(biāo)準(zhǔn)應(yīng)用層的庫(kù)函數(shù)和系統(tǒng)調(diào)用封裝函數(shù)。所有的C程序員都可以使用C庫(kù)。
從程序員的角度看,系統(tǒng)調(diào)用無(wú)關(guān)緊要,他們只需要和API打交道。相反,內(nèi)核只跟系統(tǒng)調(diào)用打交道;
關(guān)于Unix的界面設(shè)計(jì)有一句通用的格言“提供機(jī)制而不是策略”。換句話(huà)說(shuō),Unix的系統(tǒng)調(diào)用抽象出了用于完成某種確定目標(biāo)的函數(shù)。至于這些函數(shù)怎么用完全不需要內(nèi)核去關(guān)心。區(qū)別對(duì)待機(jī)制(mechanism)和策略(policy)是Unix設(shè)計(jì)的一大亮點(diǎn)。大部分編程問(wèn)題都可以被分割成兩部分:“需要提供什么功能(機(jī)制)”和“怎么實(shí)現(xiàn)這些功能(策略)”
(不明覺(jué)厲。。。)
3.系統(tǒng)調(diào)用的實(shí)現(xiàn)
您或許疑惑:“當(dāng)輸入cat proc/CPUinfo時(shí),cupinfo()函數(shù)怎么如何被調(diào)用的?”
實(shí)際上,內(nèi)核在完成引導(dǎo)后,控制流就從相對(duì)之間的“接下來(lái)調(diào)用哪個(gè)函數(shù)?”改變成為“等待模式”:等待系統(tǒng)調(diào)用、異常和中斷。
用戶(hù)空間的程序無(wú)法直接執(zhí)行內(nèi)核代碼,而是以某種方式通知系統(tǒng),告訴內(nèi)核自己需要執(zhí)行一個(gè)系統(tǒng)調(diào)用,希望系統(tǒng)切換到內(nèi)核態(tài),并執(zhí)行那里的異常處理程序。
通知內(nèi)核的機(jī)制是靠軟中斷實(shí)現(xiàn)的。過(guò)程如下:
首先,用戶(hù)程序設(shè)置系統(tǒng)調(diào)用號(hào)和外部輸入?yún)?shù);
然后,應(yīng)用程序執(zhí)行“系統(tǒng)調(diào)用”指令(特殊的機(jī)器指令,在x86上是:“INT $0x80”,)。
在x86上,這個(gè)指令:產(chǎn)生一個(gè)編號(hào)為0x80的編程異常,這個(gè)編程異常對(duì)應(yīng)的是中斷描述符表IDT中的第128項(xiàng)——也就是對(duì)應(yīng)的系統(tǒng)門(mén)描述符。門(mén)描述符中含有一個(gè)預(yù)設(shè)的內(nèi)核空間地址,它指向了系統(tǒng)調(diào)用處理程序:system_call()(別和系統(tǒng)調(diào)用服務(wù)程序混淆,這個(gè)程序在entry.S文件中用匯編語(yǔ)言編寫(xiě))。
system_call()的主要作用:
a、保存程序的現(xiàn)有狀態(tài),即進(jìn)程在用戶(hù)態(tài)下的CPU主要寄存器的值(所以叫軟中斷)(???有問(wèn)題)
b、根據(jù)系統(tǒng)調(diào)用號(hào)計(jì)算出應(yīng)該使用哪一種系統(tǒng)調(diào)用,內(nèi)核進(jìn)程查看系統(tǒng)調(diào)用表sys_call_table找到對(duì)應(yīng)的系統(tǒng)調(diào)用服務(wù)例程的入口地址;
c、轉(zhuǎn)到對(duì)應(yīng)的系統(tǒng)調(diào)用服務(wù)例程,并進(jìn)一步調(diào)用執(zhí)行內(nèi)核中的相關(guān)功能函數(shù);
d、上述系統(tǒng)服務(wù)例程執(zhí)行完成后,返回系統(tǒng)調(diào)用返回值。
e、恢復(fù)用戶(hù)程序狀態(tài),將控制權(quán)交給應(yīng)用程序。
(注意:bcd沒(méi)有問(wèn)題,ae的表述有問(wèn)題。。)
3.2系統(tǒng)調(diào)用號(hào)
在linux中,每一個(gè)系統(tǒng)調(diào)用都會(huì)被賦予一個(gè)系統(tǒng)調(diào)用號(hào)。
同時(shí),Linux有一個(gè)“未實(shí)現(xiàn)”系統(tǒng)調(diào)用sysy_ni_syscall(),它除了返回ENOSYS外,不做任何工作,這個(gè)錯(cuò)誤號(hào)就是專(zhuān)門(mén)為無(wú)效的系統(tǒng)調(diào)用設(shè)定的。
內(nèi)核中所有已經(jīng)注冊(cè)過(guò)的系統(tǒng)調(diào)用都會(huì)保存在sys_call_table表中。一般在entry.s中定義。
sys_call_table是一張由指向?qū)崿F(xiàn)各種系統(tǒng)調(diào)用的系統(tǒng)服務(wù)例程的函數(shù)指針組成的表。
ENTRY(sys_call_table)
.long SYMBOL_NAME(sys_ni_syscall) /* 0 - old "setup()" system call*/
.long SYMBOL_NAME(sys_exit)
.long SYMBOL_NAME(sys_fork)
.long SYMBOL_NAME(sys_read)
.long SYMBOL_NAME(sys_write)
.long SYMBOL_NAME(sys_open) /* 5 */
.long SYMBOL_NAME(sys_close)
.long SYMBOL_NAME(sys_waitpid)
。。。。。
.long SYMBOL_NAME(sys_capget)
.long SYMBOL_NAME(sys_capset) ?/* 185 */
.long SYMBOL_NAME(sys_sigaltstack)
.long SYMBOL_NAME(sys_sendfile)
.long SYMBOL_NAME(sys_ni_syscall) /* streams1 */
.long SYMBOL_NAME(sys_ni_syscall) /* streams2 */
.long SYMBOL_NAME(sys_vfork) /* 190 */
(還是不明白,這里面SYMBOL_NAME作用是?sys_vfork的宏定義是??)
system_call()函數(shù)通過(guò)將給定的系統(tǒng)調(diào)用好與NR-syscall作比較來(lái)檢查器有效性。如果它大于或者等于NR syscalls,該函數(shù)就返回一ENOSYS。否則,就執(zhí)行相應(yīng)的系統(tǒng)調(diào)用。
call *sys_call-table(, %eax, 4)
由于系統(tǒng)調(diào)用表中的表項(xiàng)是以32位(4字節(jié))類(lèi)型存放的,所以?xún)?nèi)核需要將給定的系統(tǒng)調(diào)用號(hào)乘以4,然后用所得的結(jié)果在該表中查詢(xún)其位
3.3????參數(shù)傳遞
除了系統(tǒng)調(diào)用號(hào)以外,大部分系統(tǒng)調(diào)用都還需要一些外部的參數(shù)輸人。所以,在發(fā)生異常的時(shí)候,應(yīng)該把這些參數(shù)從用戶(hù)空間傳給內(nèi)核。最簡(jiǎn)單的辦法就是像傳遞系統(tǒng)調(diào)用號(hào)一樣把這些參數(shù)也存放在寄存器里。在x86系統(tǒng)上,ebx, ecx, edx, esi和edi按照順序存放前五個(gè)參數(shù)。需要六個(gè)或六個(gè)以上參數(shù)的情況不多見(jiàn),此時(shí),應(yīng)該用一個(gè)單獨(dú)的寄存器存放指向所有這些參數(shù)在用戶(hù)空間地址的指針。
給用戶(hù)空間的返回值也通過(guò)寄存器傳遞。在x86系統(tǒng)上,它存放在eax寄存器中。接下來(lái)許多關(guān)于系統(tǒng)調(diào)用處理程序的描述都是針對(duì)x86版本的。但不用擔(dān)心,所有體系結(jié)構(gòu)的實(shí)現(xiàn)都很類(lèi)似。
?
3.4????參數(shù)驗(yàn)證
系統(tǒng)調(diào)用必須仔細(xì)檢查它們所有的參數(shù)是否合法有效。舉例來(lái)說(shuō),與文件I/O相關(guān)的系統(tǒng)調(diào)用必須檢查文件描述符是否有效。與進(jìn)程相關(guān)的函數(shù)必須檢查提供的PID是否有效。必須檢查每個(gè)參數(shù),保證它們不但合法有效,而且正確。
最重要的一種檢查就是檢查用戶(hù)提供的指針是否有效。試想,如果一個(gè)進(jìn)程可以給內(nèi)核傳遞指針而又無(wú)須被檢查,那么它就可以給出一個(gè)它根本就沒(méi)有訪問(wèn)權(quán)限的指針,哄騙內(nèi)核去為它拷貝本不允許它訪問(wèn)的數(shù)據(jù),如原本屬于其他進(jìn)程的數(shù)據(jù)。在接收一個(gè)用戶(hù)空間的指針之前,內(nèi)核必須保證:
? ? ?指針指向的內(nèi)存區(qū)域?qū)儆谟脩?hù)空間。進(jìn)程決不能哄騙內(nèi)核去讀內(nèi)核空間的數(shù)據(jù)。
? ? ?指針指向的內(nèi)存區(qū)域在進(jìn)程的地址空間里。進(jìn)程決不能哄騙內(nèi)核去讀其他進(jìn)程的數(shù)據(jù)。
? ? ?如果是讀,該內(nèi)存應(yīng)被標(biāo)記為可讀。如果是寫(xiě),該內(nèi)存應(yīng)被標(biāo)記為可寫(xiě)。進(jìn)程決不能繞過(guò)內(nèi)存訪問(wèn)限制。
3.5 內(nèi)核空間與用戶(hù)空間之間數(shù)據(jù)的傳遞
內(nèi)核提供了2種方法來(lái)實(shí)現(xiàn)用戶(hù)空間和內(nèi)核空間之間數(shù)據(jù)的來(lái)回拷貝。
(1)向用戶(hù)空間寫(xiě)入數(shù)據(jù):copy_to_user()函數(shù)
(2)從用戶(hù)空間讀數(shù)據(jù):copy_from_user()函數(shù)
注意copy_to_user()和copy_from_user()都有可能引起進(jìn)程阻塞。當(dāng)包含用戶(hù)數(shù)據(jù)的頁(yè)被換出到硬盤(pán)上而不是在物理內(nèi)存上的時(shí)候,這種情況就會(huì)發(fā)生。此時(shí),進(jìn)程就會(huì)休眠,直到缺頁(yè)處理程序?qū)⒃擁?yè)從硬盤(pán)重新?lián)Q回物理內(nèi)存。
3.6? ? 系統(tǒng)調(diào)用的返回值
系統(tǒng)調(diào)用(在Linux中常稱(chēng)作syscalls)通常通過(guò)函數(shù)進(jìn)行調(diào)用。它們通常都需要定義一個(gè)或幾個(gè)參數(shù)(輸入)而且可能產(chǎn)生一些副作用,例如寫(xiě)某個(gè)文件或向給定的指針拷貝數(shù)據(jù)等等。為防止和正常的返回值混淆,系統(tǒng)調(diào)用并不直接返回錯(cuò)誤碼,而是將錯(cuò)誤碼放入一個(gè)名為errno的全局變量中。通常用一個(gè)負(fù)的返回值來(lái)表明錯(cuò)誤。返回一個(gè)0值通常表明成功。如果一個(gè)系統(tǒng)調(diào)用失敗,你可以讀出errno的值來(lái)確定問(wèn)題所在。通過(guò)調(diào)用perror()庫(kù)函數(shù),可以把該變量翻譯成用戶(hù)可以理解的錯(cuò)誤字符串。
errno不同數(shù)值所代表的錯(cuò)誤消息定義在errno.h中,你也可以通過(guò)命令"man 3 errno"來(lái)察看它們。需要注意的是,errno的值只在函數(shù)發(fā)生錯(cuò)誤時(shí)設(shè)置,如果函數(shù)不發(fā)生錯(cuò)誤,errno的值就無(wú)定義,并不會(huì)被置為0。另外,在處理errno前最好先把它的值存入另一個(gè)變量,因?yàn)樵阱e(cuò)誤處理過(guò)程中,即使像printf()這樣的函數(shù)出錯(cuò)時(shí)也會(huì)改變errno的值。
當(dāng)然,系統(tǒng)調(diào)用最終具有一種明確的操作。舉例來(lái)說(shuō),如getpid()系統(tǒng)調(diào)用,根據(jù)定義它會(huì)返回當(dāng)前進(jìn)程的PID。內(nèi)核中它的實(shí)現(xiàn)非常簡(jiǎn)單:
asmlinkage long sys_ getpid(void)
{
??? return current-> tgid;
}
上述的系統(tǒng)調(diào)用盡管非常簡(jiǎn)單,但我們還是可以從中發(fā)現(xiàn)兩個(gè)特別之處。首先,注意函數(shù)聲明中的asmlinkage限定詞,這是一個(gè)小戲法,用于通知編譯器僅從棧中提取該函數(shù)的參數(shù)。所有的系統(tǒng)調(diào)用都需要這個(gè)限定詞。其次,注意系統(tǒng)調(diào)用get_pid()在內(nèi)核中被定義成sys_ getpid。這是Linux中所有系統(tǒng)調(diào)用都應(yīng)該遵守的命名規(guī)則
4.添加新的系統(tǒng)調(diào)用
給Linux添加一個(gè)新的系統(tǒng)調(diào)用是相對(duì)容易的工作。怎么設(shè)計(jì)和實(shí)現(xiàn)一個(gè)系統(tǒng)調(diào)用是難題所在,而把它添加進(jìn)內(nèi)核的過(guò)程比較簡(jiǎn)單。
在添加一個(gè)系統(tǒng)調(diào)用是我們需要考慮幾個(gè)問(wèn)題:
(1)明確系統(tǒng)調(diào)用的用途。
注意:Linux不提倡采用多用途的系統(tǒng)調(diào)用(一個(gè)系統(tǒng)調(diào)用通過(guò)傳遞不同的參數(shù)值來(lái)選擇不同類(lèi)別的功能),不要讓一個(gè)系統(tǒng)調(diào)用太復(fù)雜!
但是,這里有一個(gè)反例,ioctl()系統(tǒng)調(diào)用(可以查看詳細(xì)教程https://blog.csdn.net/zifehng/article/details/59576539)
(2)確定系統(tǒng)調(diào)用的參數(shù),返回值和錯(cuò)誤碼。
系統(tǒng)調(diào)用的接口應(yīng)該盡量簡(jiǎn)潔,設(shè)計(jì)越通用約好。這個(gè)系統(tǒng)調(diào)用可移植嗎?別對(duì)機(jī)器的字節(jié)長(zhǎng)度和字節(jié)序做假設(shè)。當(dāng)你寫(xiě)一個(gè)系統(tǒng)調(diào)用的時(shí)候,要時(shí)刻注意可移植性和健壯性,不但要考慮當(dāng)前,還要為將來(lái)做打算。
當(dāng)編譯完一個(gè)系統(tǒng)調(diào)用后,把它注冊(cè)成一個(gè)正式的系統(tǒng)調(diào)用是一件瑣碎的工作,有如下:
(1)在系統(tǒng)調(diào)用表的最后添加一項(xiàng)。每種支持該系統(tǒng)調(diào)用的硬件體系都必須做這樣的工作。從0開(kāi)始算起,系統(tǒng)調(diào)用在該表中的位置就是它的系統(tǒng)調(diào)用號(hào)。(這一點(diǎn)非常重要,在表中并不會(huì)出現(xiàn)具體的數(shù)值號(hào))
(2)對(duì)于各種體系結(jié)構(gòu),系統(tǒng)調(diào)用號(hào)必須定義在<asm/unistd.h>中。
(3)系統(tǒng)調(diào)用必須編譯進(jìn)內(nèi)核映像中(不能編譯成模塊)。可以通過(guò)把它放進(jìn)kernel/下的一個(gè)相關(guān)文件中就可以。或是自己定義一個(gè)文件,并被包含編譯(這樣比較麻煩)。
以下:
我們通過(guò)虛構(gòu)一個(gè)系統(tǒng)調(diào)用f00()來(lái)觀察一下這些步驟。
(1)首先,將sys_f00加入系統(tǒng)調(diào)用表中,對(duì)于大多數(shù)體系結(jié)構(gòu)來(lái)說(shuō),sys_call_table表位于entry.s文件中,形式如下:
ENTRY(sys_call_table)
.long SYMBOL_NAME(sys_ni_syscall) /* 0 - old "setup()" system call*/
.long SYMBOL_NAME(sys_exit)
.long SYMBOL_NAME(sys_fork)
.long SYMBOL_NAME(sys_read)
.long SYMBOL_NAME(sys_write)
.long SYMBOL_NAME(sys_open) /* 5 */
......
我們將新的系統(tǒng)調(diào)用添加在表的尾行:
.long SYMBOL_NAME(sys_f00)
雖然,這里沒(méi)有明確指明系統(tǒng)調(diào)用號(hào),但我們加入的這個(gè)系統(tǒng)調(diào)用被按照次序分配給了283這個(gè)系統(tǒng)調(diào)用號(hào)!
對(duì)于每種需要支持的體系結(jié)構(gòu),我們必須將自己的系統(tǒng)調(diào)用添加到其sys_call_table中。(說(shuō)明表不止一個(gè),每種體系都有一個(gè))
(2)將自己的系統(tǒng)調(diào)用號(hào)加入<asm/unistd.h>中。
它的格式如下:
/*本文件包含系統(tǒng)調(diào)用號(hào)*/
#define __NR_read ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0
__SYSCALL(__NR_read, sys_read)
#define __NR_write ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?1
__SYSCALL(__NR_write, sys_write)
#define __NR_open ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 2
__SYSCALL(__NR_open, sys_open)
#define __NR_close ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?3
__SYSCALL(__NR_close, sys_close)
..................
然后,我們?cè)僭摿斜淼募尤胱约旱南到y(tǒng)調(diào)用號(hào)
#define? __NR_f00? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 283
(3)f00系統(tǒng)調(diào)用的函數(shù)實(shí)現(xiàn)。
因?yàn)閒00系統(tǒng)調(diào)用要被編譯進(jìn)內(nèi)核映像,因此我們將它寫(xiě)進(jìn) kernel/sys.c 文件中。
asmlinkage long sys_f00(void)
{
return 1;
}
這樣嚴(yán)格來(lái)說(shuō),現(xiàn)在就可以在用戶(hù)空間調(diào)用f00()系統(tǒng)調(diào)用了。
?
?
總結(jié)
以上是生活随笔為你收集整理的linux系统调用理解之摘录(2)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: linux系统调用理解之摘录(1)
- 下一篇: Linux 发行版与Linux内核