POSIX和C庫


原文鏈接:https://www.cnblogs.com/xkfz007/articles/2176983.html

參考鏈接:https://blog.csdn.net/weixin_42048417/article/details/80949598

                https://blog.csdn.net/gong_1/article/details/19201027?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

摘要:《Linux內核修煉之道》第5章講解系統調用,它是應用程序和內核間的橋梁,學習並理解它是我們走向內核的一個很好的過渡。本節為大家介紹系統調用、POSIX、C庫、系統命令和內核函數。

5.1.1  系統調用、POSIX、C庫、系統命令和內核函數

(1)系統調用和POSIX。

系統調用雖然是內核和用戶應用程序之間的溝通橋梁,是用戶應用程序訪問內核的入口點,但通常情況下,應用程序是通過操作系統提供的應用編程接口(API)而不是直接通過系統調用來編程。

操作系統API的主要作用是把操作系統的功能完全展示出來,提供給應用程序,基於該操作系統,與文件、內存、時鍾、網絡、圖形、各種外設等互操作的能力。此外,操作系統API通常還提供許多工具類的功能,比如操縱字符串、各種數據類型、時間日期等。

在UNIX世界里,最通用的操作系統API基於POSIX(Portable Operating System Interface of UNIX,可移植操作系統接口)標准。POSIX的誕生和UNIX的發展密不可分,UNIX於20世紀70年代誕生於Bell lab,並於20世紀80年代向美各大高校分發V7版的源碼以做研究。UC Berkeley在V7的基礎上開發了BSD UNIX。

后來很多商業廠家意識到UNIX的價值也紛紛以Bell Lab的System V或BSD為基礎來開發自己的UNIX,較著名的有Sun OS、AIX、VMS等。雖然這帶來了UNIX的繁榮,但由於各廠家對UNIX的開發各自為政,UNIX的版本相當混亂,給軟件的可移植性帶來很大困難, 對UNIX的發展極為不利。

為結束這種局面,IEEE制訂了POSIX標准,目標是提供一套大體上基於UNIX的可移植 操作系統標准,提高UNIX環境下應用程序的可移植性。然而,POSIX並不局限於UNIX。許多其他的操作系統,例如DEC OpenVMS和Microsoft Windows NT,都支持POSIX標准。

POSIX標准定義了"POSIX兼容"的操作系統所必須提供的服務。Linux兼容於 POSIX標准,提供了根據POSIX而定義的API函數。這些API函數和系統調用之間有着直接的關系,一個API函數可以由一個系統調用實現,也可以 通過調用多個系統調用來實現,還可以完全不使用任何系統調用。

(2)系統調用和C庫。

操作系統API通常都以C庫的方式提供,Linux也是如此。C庫提供了POSIX的絕大部分API,同時,內核提供的每個系統調用在C庫中都具有相應的封裝函數。系統調用與其C庫封裝函數的名稱常常相同,比如,read系統調用在C庫中的封裝函數即為read函數。

C庫中的系統調用封裝函數在最終調用到相應系統調用之前,往往不做多少額外的工作。不過,某些情況下會有些例外,比如對於兩個相關的系統調用truncate和truncate64,C庫中的封裝函數truncate函數即需要決定它們中的哪個應該最終被調用。

當然,如圖5.1所示,系統調用和C庫函數之間並不是一一對應的關系。可能幾個不同的函數會 調用到同一個系統調用,比如malloc函數和free函數都是通過brk系統調用來擴大或縮小進程的堆棧,execl、execlp、execle、 execv、execvp和execve函數都是通過execve系統調用來執行一個可執行文件。

也有可能一個函數調用多個系統調用。更有些函數並不依賴於任何系統調用,比如strcpy函數(復制字符串)和atoi函數(轉換ASCII為整數),因為它們並不需要向內核請求任何服務。

 

圖5.1  C庫函數與系統調用

實際上,從用戶的角度看,系統調用和C庫之間的區別並不重要,他們只需通過C庫函數完成所需功能。相反,從內核的角度看,需要考慮的則是提供哪些針對確定目的的系統調用,並不需要關注它們如何被使用。

(3)系統調用與系統命令。

系統命令位於C庫的更上層,是利用C庫實現的可執行程序,比如最為常用的ls、cd等命令。

strace工具可以跟蹤命令的執行,使用希望跟蹤的命令為參數,並顯示出該命令執行過程中所使用到的所有系統調用。比如,如果希望了解在執行pwd命令時都調用了哪些系統調用,可以使用下面的命令:

$strace pwd
結果會產生大量的信息,顯示出pwd命令執行過程中所調用到的各個系統調用:
……  
write(1, "/usr/src/linux-2.6.23\n", 22/usr/src/linux-2.6.23) = 22  
close(1)                                = 0  
munmap(0xb7f5a000, 4096)                = 0  
exit_group(0) 

(4)系統調用和內核函數。

內核函數與C庫函數的區別僅僅是內核函數在內核實現,因此必須遵守內核編程的規則。

系統調用最終必須具有明確的操作。用戶應用程序通過系統調用進入內核后,會執行各個系統調用對應的內核函數,即系統調用服務例程,比如系統調用getpid的服務例程是內核函數sys_getpid。

系統調用服務例程之外,內核中存在着大量的內核函數。有些局限於某個內核文件自己使用,有些則是export出來供內核其他部分共同使用。對於export出來的內核函數,可以使用ksyms命令或通過/proc/ksyms文件查看。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM