Linux 库函数与系统调用的关系与区别
上周總結(jié)了《C 標(biāo)準(zhǔn)庫的基礎(chǔ) IO》,其實(shí)這些功能函數(shù)通過「系統(tǒng)調(diào)用」也能實(shí)現(xiàn)相應(yīng)功能。這次文章并不是要詳細(xì)介紹各系統(tǒng)調(diào)用接口的使用方法,而是要深入理解「庫函數(shù)」與「系統(tǒng)」調(diào)用之間的關(guān)系和區(qū)別。
一、系統(tǒng)調(diào)用
系統(tǒng)調(diào)用,我們可以理解是操作系統(tǒng)為用戶提供的一系列操作的接口(API),這些接口提供了對(duì)系統(tǒng)硬件設(shè)備功能的操作。這么說可能會(huì)比較抽象,舉個(gè)例子,我們最熟悉的?hello world?程序會(huì)在屏幕上打印出信息。程序中調(diào)用了?printf()?函數(shù),而庫函數(shù)?printf?本質(zhì)上是調(diào)用了系統(tǒng)調(diào)用?write()?函數(shù),實(shí)現(xiàn)了終端信息的打印功能。
二、庫函數(shù)
庫函數(shù)可以理解為是對(duì)系統(tǒng)調(diào)用的一層封裝。系統(tǒng)調(diào)用作為內(nèi)核提供給用戶程序的接口,它的執(zhí)行效率是比較高效而精簡的,但有時(shí)我們需要對(duì)獲取的信息進(jìn)行更復(fù)雜的處理,或更人性化的需要,我們把這些處理過程封裝成一個(gè)函數(shù)再提供給程序員,更方便于程序猿編碼。
庫函數(shù)有可能包含有一個(gè)系統(tǒng)調(diào)用,有可能有好幾個(gè)系統(tǒng)調(diào)用,當(dāng)然也有可能沒有系統(tǒng)調(diào)用,比如有些操作不需要涉及內(nèi)核的功能。可以參考下圖來理解庫函數(shù)與系統(tǒng)調(diào)用的關(guān)系。
三、系統(tǒng)調(diào)用意義
- 避免了用戶直接對(duì)底層硬件進(jìn)行編程。比如最簡單的hello world程序是將信息打印到終端,終端對(duì)系統(tǒng)來說是硬件資源,如果沒有系統(tǒng)調(diào)用,用戶程序需要自己編寫終端設(shè)備的驅(qū)動(dòng),以及控制終端如何顯示的代碼。
- 隱藏背后的技術(shù)細(xì)節(jié)。比如讀寫文件,如果使用了系統(tǒng)調(diào)用,用戶程序無須關(guān)心數(shù)據(jù)在磁盤的哪個(gè)磁道和扇區(qū),以及數(shù)據(jù)要加載到內(nèi)存什么位置。
- 保證系統(tǒng)的安全性和穩(wěn)定性。要知道用戶程序是不能直接操作內(nèi)核地址空間的,比如一個(gè)剛出道的程序猿,讓他直接去訪問內(nèi)核底層的數(shù)據(jù),那么內(nèi)核系統(tǒng)的安全性就無法保證。而系統(tǒng)調(diào)用的功能是由內(nèi)核來實(shí)現(xiàn),用戶只需要調(diào)用接口,無需關(guān)心細(xì)節(jié),也避免了系統(tǒng)的安全隱患。
- 方便程序的移植性。如果針對(duì)一個(gè)系統(tǒng)資源的功能操作比如 write(),大家都按照自己思路去實(shí)現(xiàn)這個(gè)功能,那么我們寫出來的程序的移植性就會(huì)非常差。
總而言之,我們只需要把系統(tǒng)調(diào)用當(dāng)作一個(gè)接口,而這個(gè)接口能實(shí)現(xiàn)我們的一個(gè)功能,既方便又安全。
四、庫函數(shù) vs 系統(tǒng)調(diào)用
參考了《C 專家編程》書籍中的附錄 A.4,書中關(guān)于兩者區(qū)別的回答是這樣的,函數(shù)庫調(diào)用是語言或應(yīng)用程序的一部分,而系統(tǒng)調(diào)用是操作系統(tǒng)的一部分。
- 所有 C 函數(shù)庫是相同的,而各個(gè)操作系統(tǒng)的系統(tǒng)調(diào)用是不同的。
- 函數(shù)庫調(diào)用是調(diào)用函數(shù)庫中的一個(gè)程序,而系統(tǒng)調(diào)用是調(diào)用系統(tǒng)內(nèi)核的服務(wù)。
- 函數(shù)庫調(diào)用是與用戶程序相聯(lián)系,而系統(tǒng)調(diào)用是操作系統(tǒng)的一個(gè)進(jìn)入點(diǎn)
- 函數(shù)庫調(diào)用是在用戶地址空間執(zhí)行,而系統(tǒng)調(diào)用是在內(nèi)核地址空間執(zhí)行
- 函數(shù)庫調(diào)用的運(yùn)行時(shí)間屬于「用戶」時(shí)間,而系統(tǒng)調(diào)用的運(yùn)行時(shí)間屬于「系統(tǒng)」時(shí)間
- 函數(shù)庫調(diào)用屬于過程調(diào)用,開銷較小,而系統(tǒng)調(diào)用需要切換到內(nèi)核上下文環(huán)境然后切換回來,開銷較大
- 在C函數(shù)庫libc中大約 300 個(gè)程序,在 UNIX 中大約有 90 個(gè)系統(tǒng)調(diào)用
- 函數(shù)庫典型的 C 函數(shù):system, fprintf, malloc,而典型的系統(tǒng)調(diào)用:chdir, fork, write, brk
據(jù)書中記載,庫函數(shù)調(diào)用大概花費(fèi)時(shí)間為半微妙,而系統(tǒng)調(diào)用所需要的時(shí)間大約是庫函數(shù)調(diào)用的 70 倍(35微秒),因?yàn)橄到y(tǒng)調(diào)用會(huì)有內(nèi)核上下文切換的開銷。純粹從性能上考慮,你應(yīng)該盡可能地減少系統(tǒng)調(diào)用的數(shù)量,但是,你必須記住許多 C 函數(shù)庫中的程序通過系統(tǒng)調(diào)用來實(shí)現(xiàn)功能。
五、正確理解庫函數(shù)高效于系統(tǒng)調(diào)用
首先解釋,上述說明的庫函數(shù)性能遠(yuǎn)高于系統(tǒng)調(diào)用的前提是,庫函數(shù)種沒有使用系統(tǒng)調(diào)用。再來解釋下某些包含系統(tǒng)調(diào)用的庫函數(shù),然而其性能確實(shí)也要高于系統(tǒng)調(diào)用。比如上篇文章中關(guān)于文件 IO 函數(shù) fread、fwrite、fputc、fgetc 等,這些函數(shù)通常情況下性能確實(shí)比系統(tǒng)調(diào)用高,原因在于這些庫函數(shù)使用了緩沖區(qū),減少了系統(tǒng)調(diào)用的次數(shù),因而顯得性能比較高。
六、系統(tǒng)調(diào)用是如何運(yùn)行的
上述內(nèi)容基本說清楚了庫函數(shù)與系統(tǒng)調(diào)用的概念以及它們之間的關(guān)系,下面我們來理解系統(tǒng)調(diào)用到底是如何運(yùn)行的。
當(dāng)一個(gè)進(jìn)程正在運(yùn)行,遇到讀寫文件操作,會(huì)發(fā)生一個(gè)中斷,中斷后系統(tǒng)會(huì)把當(dāng)前用戶進(jìn)程的一些寄存器信息保存在內(nèi)核堆棧中,接著去處理中斷服務(wù)程序,這里是要去執(zhí)行系統(tǒng)調(diào)用,Linux 中通過執(zhí)行?int $0x80?來執(zhí)行系統(tǒng)調(diào)用的中斷,但內(nèi)核實(shí)現(xiàn)了很多系統(tǒng)調(diào)用,這時(shí)需要傳遞「系統(tǒng)調(diào)用號(hào)」來指明需要哪個(gè)系統(tǒng)調(diào)用。
為了更清楚的說明系統(tǒng)調(diào)用的過程,我們這里參考網(wǎng)上的一段代碼來實(shí)現(xiàn)系統(tǒng)調(diào)用:
int main() {time_t tt; struct tm *t; asm volatile ("mov $0,%%ebx\n\t""mov $0xd,%%eax\n\t""int $0x80\n\t""mov %%eax,%0\n\t": "=m" (tt)); t = localtime(&tt);printf("Time: %d-%02d-%02d %02d:%02d:%02d\n",t->tm_year + 1900,t->tm_mon + 1, t->tm_mday,t->tm_hour, t->tm_min, t->tm_sec); }[linuxblogs@host ~]$ gcc a.c -oa && ./a Time: 2018-05-06 03:23:46首先通過?mov $0xd %%eax?來將系統(tǒng)調(diào)用放入?%eax?寄存器中,time() 的系統(tǒng)調(diào)用號(hào)是 13,然后執(zhí)行?int $0x80?系統(tǒng)就會(huì)去執(zhí)行 time() 這個(gè)系統(tǒng)調(diào)用了。其實(shí)代碼中的匯編部分就是實(shí)現(xiàn) time() 系統(tǒng)調(diào)用的功能,匯編代碼不懂沒關(guān)系(我也不太懂),這里主要是為了說清楚系統(tǒng)調(diào)用的整個(gè)過程。
==================================================================================================
問:fopen open sys_open 內(nèi)核函數(shù) 系統(tǒng)調(diào)用區(qū)別?
答:
系統(tǒng)調(diào)用是有一個(gè)?CPU?運(yùn)行等級(jí)的提升問題.?用戶代碼在?3?級(jí),?操作系統(tǒng)代碼在?0?級(jí).
open?是在?Ring?3?級(jí)對(duì)系統(tǒng)調(diào)用的一個(gè)包裝.?
所有的系統(tǒng)函數(shù)只有一個(gè)系統(tǒng)調(diào)用入口,?int?$0x80,?在這條指令之前把調(diào)用的函數(shù)對(duì)應(yīng)的功能號(hào)放到?%eax?寄存器.
這條指令產(chǎn)生一個(gè)中斷,?CPU?切換到中斷處理程序,?運(yùn)行等級(jí)從?Ring?3?級(jí)切換到?Ring?0?級(jí).?開始在內(nèi)核中運(yùn)行.?內(nèi)核再根據(jù)?%eax?中的功能號(hào)來調(diào)用不同的函數(shù).?sys_open?就是內(nèi)核中處理?open?對(duì)應(yīng)的功能號(hào)的函數(shù).
操作系統(tǒng)提供的原型都是?C?接口的,?其它語言要用再進(jìn)行包裝就是.
轉(zhuǎn)載:https://www.cnblogs.com/liwei0526vip/p/8998751.html
總結(jié)
以上是生活随笔為你收集整理的Linux 库函数与系统调用的关系与区别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: uboot2012(一)分析重定位
- 下一篇: Linux 下系统调用的三种方法