天天看點

[架構之路-59]:目标系統 - 平台軟體 - 基礎中間件 - POSIX(可移植作業系統接口)與标準庫函數libc

目錄

​​第1章 POSIX(可移植作業系統接口)概述​​

​​1.1 什麼是POSIX​​

​​1.2 釋出者-IEEE​​

​​1.3 标準的下載下傳位置​​

​​1.4 标準的起源​​

​​1.5 誰遵守這個标準​​

​​第2章 POSIX接口的支援方式​​

​​2.1POSIX的好處:可移植性​​

​​2.3 程式的可移植性及其本質​​

​​2.4 示例​​

​​第3章 glibc主要功能簡介​​

​​3.1 c語言庫概述​​

​​3.2 glibc概述​​

​​3.3 POSIX标準的C語言頭檔案​​

第1章 POSIX(可移植作業系統接口)概述

1.1 什麼是POSIX

可移植作業系統接口(英語:Portable Operating System Interface,縮寫為POSIX)。

POSIX是為要在各種​​UNIX​​​​作業系統​​上運作軟體,而定義的一系列互相關聯的OS API标準的總稱。

1.2 釋出者-IEEE

釋出者為電氣與電子工程師協會(Institute of Electrical and Electronics Engineers),簡稱IEEE。這個協會老牛了【該組織在太空、計算機、電信、生物醫學、電力及消費性電子産品等領域中都是主要的權威】!

其正式稱呼為IEEE Std 1003,而國際标準名稱為ISO/​​IEC​​​ 9945。此标準源于一個大約開始于1985年的項目。POSIX這個名稱是由​​理查德·斯托曼​​(RMS)應IEEE的要求而提議的一個易于記憶的名稱。它基本上是Portable Operating System Interface(可移植作業系統接口)的縮寫,而X則表明其對Unix API的傳承。

IEEE,總部位于美國紐約,是一個國際性的電子技術與資訊科學工程師的協會,也是目前全球最大的非營利性專業技術學會。IEEE緻力于電氣、電子、計算機工程和與科學有關的領域的開發和研究,在太空、計算機、電信、生物醫學、電力及消費性電子産品等領域已制定了1300多個行業标準,現已發展成為具有較大影響力的國際學術組織

1.3 标準的下載下傳位置

标準線上位址: ​​http://www.unix.org/version3/online.html​​ 注冊後可以線上閱讀或者下載下傳。

1.4 标準的起源

POSIX是Unix的标準。

1974年,貝爾實驗室正式對外釋出Unix。因為涉及到反壟斷等各種原因,加上早期的Unix不夠完善,于是貝爾實驗室以慷慨的條件向學校提供源代碼,是以Unix在大專院校裡獲得了很多支援并得以持續發展。

于是出現了好些獨立開發的與Unix基本相容但又不完全相容的OS,通稱Unix-like OS。

包括:

  1. 美國加州大學伯克利分校的Unix4.xBSD(Berkeley Software Distribution)。
  2. 貝爾實驗室釋出的自己的版本,稱為System V Unix。
  3. 其他廠商的版本,比如Sun Microsystems的Solaris系統,則是從這些原始的BSD和System V版本中衍生而來。
[架構之路-59]:目标系統 - 平台軟體 - 基礎中間件 - POSIX(可移植作業系統接口)與标準庫函數libc

20世紀80年代中期,Unix廠商試圖通過加入新的、往往不相容的特性來使它們的程式與衆不同。

局面非常混亂,麻煩也就随之而來了。

為了提高相容性和應用程式的可移植性,阻止這種趨勢, IEEE(電氣和電子工程師協會)開始努力标準化Unix的開發,後來由 Richard Stallman命名為“Posix”。

這套标準涵蓋了很多方面,比如Unix系統調用的C語言接口、shell程式和工具、線程及網絡程式設計。

有了這個規範,你就可以調用通用的API了,Linux提供的POSIX系統調用在Unix上也能執行,是以學習Linux的底層接口最好就是了解POSIX标準。

1.5 誰遵守這個标準

首先就是大名鼎鼎的Unix和Linux了,除此之外還有蘋果的作業系統也是Unix-based的。

Windows從WinNT開始就有相容POSIX的考慮。這是因為當年在要求嚴格的領域,Unix地位比Windows高。為了把Unix使用者拉到Windows陣營,被迫支援POSIX。現在Win10對 Linux/POSIX 支援好。

[架構之路-59]:目标系統 - 平台軟體 - 基礎中間件 - POSIX(可移植作業系統接口)與标準庫函數libc

第2章 POSIX接口的支援方式

2.1POSIX的好處:可移植性

Linux下提供兩種方式支援可移植性:

系統調用(system call)和庫函數調用(Library functions)。

(1)系統調用

系統調用是通向作業系統本身的接口,是面向底層硬體的。

通過系統調用,可以使得使用者态運作的程序與硬體裝置(如CPU、磁盤、列印機等)進行互動,是作業系統留給應用程式的一個接口。

(2)庫函數(符合POSIX标準)

庫函數(Library function)是把函數放到庫裡,供别人使用的一種方式。

方法是把一些常用到的函數編完放到一個檔案裡,供不同的人進行調用。一般放在.lib檔案中。

庫函數調用則是面向應用開發的,庫函數可分為兩類,

  • 一類是C語言标準規定的庫函數,
  • 一類是編譯器特定的庫函數。

(由于版權原因,庫函數的源代碼一般是不可見的,但在頭檔案中你可以看到它對外的接口)。

glibc 是 Linux 下使用的開源的标準 C 庫,它是 GNU 釋出的 libc 庫,即運作時庫。這些基本函數都是被标準化了的,而且這些函數通常都是用彙編直接實作的。

glibc 為程式員提供豐富的 API(Application Programming Interface),這些API都是遵循POSIX标準的,API的函數名,傳回值,參數類型等都必須按照POSIX标準來定義。

POSIX相容也就指定這些接口函數相容,但是并不管API具體如何實作。

2.2 系統調用與庫函數的關系

[架構之路-59]:目标系統 - 平台軟體 - 基礎中間件 - POSIX(可移植作業系統接口)與标準庫函數libc
[架構之路-59]:目标系統 - 平台軟體 - 基礎中間件 - POSIX(可移植作業系統接口)與标準庫函數libc

如上圖所示:

  1. 歸屬不同:庫函數是語言或應用程式的一部分,而系統調用是核心提供給應用程式的接口,屬于系統的一部分
  2. 位址空間不同:庫函數在使用者位址空間執行,系統調用是在核心位址空間執行,庫函數運作時間屬于使用者時間,系統調用屬于系統時間,庫函數開銷較小,系統調用開銷較大
  3. 依賴性不同:系統調用依賴于平台,庫函數并不依賴
  4. 庫函數是應用程式和庫函數之間一座橋梁。
[架構之路-59]:目标系統 - 平台軟體 - 基礎中間件 - POSIX(可移植作業系統接口)與标準庫函數libc

2.3 程式的可移植性及其本質

那麼目标代碼和啟動代碼是怎麼生成的呢? 答案是編譯器。

程式設計語言編寫的程式首先要被編譯器編譯成目标代碼(0、1代碼),然後在目标代碼的前面插入啟動代碼,最終生成了一個完整的程式。

要注意的是,程式中為通路特定裝置(如顯示器)或者作業系統(如windows xp 的API)的特殊功能而專門編寫的部分通常是不能移植的。

綜上所述,一個程式設計語言的可移植性取決于

  1. 不同平台編譯器的數量
  2. 對特殊硬體或作業系統的依賴性

移植是基于作業系統的。

(1)二進制代碼:

我們需要注意一點:基于各種作業系統平台不同,應用程式在二進制代碼級别是不能直接移植的。

(2)OS API源代碼

我們隻能在源代碼層去思考可移植問題,在API層面上由于各個作業系統的命名規範、系統調用等自身原因,在OS API層面上實作可移植也是不大可能的。

(3)C語言函數庫

在各個平台下,我們預設C标準庫中的函數都是一樣的,這樣基本可以實作可移植。

但是對于C庫本身而言,在各種作業系統平台下其内部實作是完全不同的,也就是說C庫封裝了作業系統API在其内部的實作細節。

是以,C語言提供了我們在代碼級的可移植性,即這種可移植是通過C語言這個中間層來完成的。

例如在我們的代碼中下功夫。以下代碼可以幫助我們實作各平台之間的可移植:

#ifdef _WINDOWS_
       CreateThread();      //windows下線程的建立
#else
       Pthread_create();    //Linux下線程的建立
#endif      

對于頭檔案,也使用同樣的預編譯宏來實作。如:

#ifndef _WINDOWS_
       #include <windows.h>
#else
       #include <thread.h>
#endif      

這樣就可以實作代碼的可移植了。在編譯的時候隻要通過#define就可以選擇在那個平台下完成程式的編譯。有c語言庫實作對不同作業系統平台的屏蔽。

綜上所述,我們都是将C,C++等各種語言庫當作中間層,以實作其一定程度上的可移植。如今,語言的跨平台的程式都是以這樣的方式實作的。但是在不同的平台下,仍需要重新編譯。

2.4 示例

如下圖是Linux系統調用的大概流程。

當應用程式調用printf()函數時,printf函數會調用C庫中的printf,繼而調用C庫中的write,C庫最後調用核心的write()。

而另一些則不會使用系統調用,比如strlen, strcat, memcpy等。

[架構之路-59]:目标系統 - 平台軟體 - 基礎中間件 - POSIX(可移植作業系統接口)與标準庫函數libc

printf函數執行過程中,程式運作狀态切換如下:

使用者态–>系統調用–>核心态–>傳回使用者态      

printf函數、glibc庫和系統調用在系統中關系圖如下:

[架構之路-59]:目标系統 - 平台軟體 - 基礎中間件 - POSIX(可移植作業系統接口)與标準庫函數libc

第3章 glibc主要功能簡介

3.1 c語言庫概述

glibc和libc都是Linux下的C函數庫:

libc是Linux下的ANSI C函數庫,

glibc是Linux下的GUN C函數庫。

glibc是遵循POSIX标準的C語言函數庫,是以,我們可以通過glibc來了解POSIX接口的主要功能。

3.2 glibc概述

glibc是​​GNU​​​釋出的libc庫,即c​​運作庫​​​。glibc是​​linux系統​​​中最底層的​​api​​,幾乎其它任何運作庫都會依賴于glibc。

glibc除了封裝​​linux​​​作業系統所提供的​​系統服務​​外,它本身也提供了許多其它一些必要其他功能服務的實作。

由于glibc囊括了幾乎所有的 ​​UNIX​​ 通行的标準,可以想見其内容包羅萬象。

glibc是一種按照​​LGPL​​​許可協定釋出的,自由的,公開源代碼的,友善從網絡下載下傳的C的編譯程式。GNU C運作期庫,是一種C​​函數庫​​​,是程式運作時使用到的一些​​API​​​集合,它們一般是已預先​​編譯​​​好,以​​二進制​​​代碼形式存在​​Linux​​類系統中,GNU C運作期庫通常作為GNU C編譯程式的一個部分釋出。

glibc最初是​​自由軟體基金會​​​(FSF)為其​​GNU​​​作業系統所寫,但目前最主要的應用是配合​​Linux核心​​,成為GNU/Linux作業系統一個重要的組成部分。

3.3 POSIX标準的C語言頭檔案

(1)基本計算

<assert.h> ---------------------- 驗證程式斷言

<complex.h> ---------------------- 支援複數算術運算

<ctype.h> ---------------------- 字元類型

<errno.h> ---------------------- 出錯碼

<fenv.h> ---------------------- 浮點環境

<float.h> ---------------------- 浮點常量

<inttypes.h> ---------------------- 整型格式轉換

<iso646.h> ---------------------- 替代關系操作符宏

<limits.h> ---------------------- 實作常量

<locale.h> ---------------------- 局部類别

<math.h> ---------------------- 數學常量

<setjmp.h> ---------------------- 非局部goto

<signal.h> ---------------------- 信号

<stdarg.h> ---------------------- 可變參數表

<stdbool.h> ---------------------- 布爾類型和值

<stddef.h> ---------------------- 标準定義

<stdint.h> ---------------------- 整型

<stdio.h> ---------------------- 标準I/O庫

<stdlib.h> ---------------------- 實用程式庫函數

<string.h> ---------------------- 字元串操作

<tgmath.h> ---------------------- 通用類型數學宏

<time.h> ---------------------- 時間和日期

<wchar.h> ---------------------- 擴充的多位元組和寬字元支援

<wctype.h> ---------------------- 寬字元分類和映射支援

(2)網絡與檔案

<dirent.h> ---------------------- 目錄項

<fcntl.h> ---------------------- 檔案控制

<fnmatch.h> ---------------------- 檔案名比對類型

<glob.h> ---------------------- 路徑名模式比對類型

<grp.h> ---------------------- 組檔案

<netdb.h> ---------------------- 網絡資料庫操作

<pwd.h> ---------------------- 密碼檔案

<regex.h> ---------------------- 正規表達式

<tar.h> ---------------------- tar歸檔值

<termios.h> ---------------------- 終端I/O

<unistd.h> ---------------------- 符号常量

<utime.h> ---------------------- 檔案時間

<wordexp.h> ---------------------- 字擴充類型

<arpa/inet.h> ---------------------- Internet定義

<net/if.h> ---------------------- socket套接字本地接口

<netinet/in.h> ---------------------- Internet位址族

<netinet/tcp.h> ---------------------- 傳輸控制協定定義

<sys/mman.h> ---------------------- 記憶體管理聲明

<sys/select.h> ---------------------- select函數

<sys/socket.h> ---------------------- 套接字接口

<sys/stat.h> ---------------------- 檔案狀态

<sys/times.h> ---------------------- 程序時間

<sys/types.h> ---------------------- 基本系統資料類型

<sys/un.h> ---------------------- UNIX域套接字定義

<sys/utsname.h> ---------------------- 系統名

<sys/wait.h> ---------------------- 程序控制

(3)POSIX标準定義的XSI擴充頭檔案(26項) 

繼續閱讀