UNIX 環境高級編程|UNIX 系統概述

      網友投稿 775 2025-03-31

      GitHub: https://github.com/storagezhang

      Emai: debugzhang@163.com

      本文為《UNIX 環境高級編程》第 1 章學習筆記

      1.2 UNIX 體系結構

      系統調用

      內核的接口被稱為系統調用。公用函數庫構建在系統調用接口之上,應用程序既可使用公用函數庫,也可使用系統調用。

      shell

      shell 是一個特殊的應用程序,為運行其他應用程序提供了一個接口。

      man

      man (選項) (參數)

      1.4 文件和目錄

      工作目錄

      每個進程都有一個工作目錄,有時稱其為當前工作目錄。所有的相對路徑名都是從工作目錄開始解釋。進程可以用 chdir 函數更改其工作目錄。

      起始目錄

      登錄時,工作目錄設置為起始目錄,該起始目錄從口令文件中相應用戶的登錄項中取得。

      1.5 輸入和輸出

      文件描述符

      文件描述符通常是一個小的非負整數,內核用以標識一個特定進程正在訪問的文件。當內核打開一個現有文件或創建一個新文件時,它都返回一個文件描述符。在讀和寫文件時,可以使用這個文件描述符。

      標準輸入、標準輸出和標準錯誤

      每當運行一個新程序時,所有的 shell 都為其打開 3 個文件描述符,即標準輸入、標準輸出和標準錯誤。如果不做特殊處理,這 3 個描述符都鏈接向終端。

      不帶緩沖的 I/O

      函數 open、read、write、lseek 以及 close 提供了不帶緩沖的 I/O。這些函數都是用文件描述符。

      標準 I/O

      標準 I/O 函數為那些不帶緩沖的 I/O 函數提供了一個帶緩沖的接口。使用標準 I/O 函數無需擔心如何選擇最佳的緩沖區大小。

      1.6 程序和進程

      程序

      程序是一個存儲在磁盤上某個目錄中的可執行文件。內核使用 exec 函數(7 個 exec 函數之一),將程序讀入內存,并執行程序。

      進程和進程 ID

      程序的執行實例被稱為進程。

      UNIX 系統確保每個進程都有一個唯一的數字標識符,稱為進程 ID。進程 ID 總是一個非負整數。

      進程控制

      有 3 個用于進程控制的主要函數:fork、exec 和 waitpid。

      exec 函數有 7 種變體,但經常把它們統稱為 exec 函數。

      fork 和跟隨其后的 exec 兩者的組合就是某些操作系統所稱的產生一個新進程。在 UNIX 系統中,這兩部分分離成兩個獨立的函數。

      線程和線程 ID

      一個進程內的所有線程共享同一地址空間、文件描述符、棧以及與進程相關的屬性。

      因為它們能訪問同一存儲區,所以各線程在訪問共享數據時需要采取同步措施以避免不一致性。

      與進程相同,線程也用 ID 標識。但是,線程 ID 只在它所屬的進程內起作用。一個進程中的線程 ID 在另一個進程中沒有意義。當在一進程中對某個特定線程進行處理時,我們可以使用該線程的 ID 引用它。

      1.7 出錯處理

      errno

      當 UNIX 系統函數出錯時,通常會返回一個負值,而且整型變量 errno 通常被設置為具有特定信息的值。

      文件 中定義了 errno 以及可以賦予它的各種常量。

      這些常量都以字符 E 開頭。

      在 Linux 中,出錯常量在 errno(3) 手冊頁中列出。

      在支持線程的環境中,多個線程共享進程地址空間,每個線程都有屬于它自己的局部 errno 以避免一個線程干擾另一個線程。

      如果沒有出錯,errno 值不會被歷程清除。因此,僅當函數的返回值指明出錯時,才檢驗其值。

      任何函數都不會將 errno 值設置為 0,而且在 中定義的所有常量都不為 0。

      C 標準定義了兩個函數,它們用于打印出錯信息:

      #include char *streror(int errnum);

      strerror 函數將 errnum(通常就是 errno 值)映射為一個出錯消息字符串,并且返回此字符串的指針。

      #include void perror(const char *msg);

      perror 函數基于 errno 的當前值,在標準錯誤上產生一條出錯消息,然后返回。

      出錯恢復

      可將在 中定義的各種出錯分成兩類:致命性的和非致命性的。

      對于致命性的錯誤,無法執行恢復動作。

      最多只能在用戶屏幕上打印一條出錯消息或者將一條出錯消息寫入日志,然后退出。

      對于非致命性的出錯,有時可以較妥善地進行處理。

      大多數非致命性出錯是暫時的(如資源短缺)。

      與資源相關的非致命性出錯包括:

      EAGAIN

      ENFILE

      ENOBUFS

      UNIX 環境高級編程|UNIX 系統概述

      ENOLCK

      ENOSPC

      EWOULDBLOCK

      ENOMEM (有時)

      EBUSY(中斷一個慢速系統調用時)

      對于資源相關的非致命性出錯的典型恢復操作是延遲一段時間,然后重試。

      1.8 用戶標識

      用戶 ID

      口令文件登錄項中的用戶 ID(user ID)是一個數值,它向系統標識各個不同的用戶。

      系統管理員在確定一個用戶的登錄名的同時,確定其用戶 ID。

      用戶不能更改其用戶 ID。

      用戶 ID 為 0 的用戶為根用戶(root)或超級用戶(superuser),稱這種用戶的特權為超級用戶特權。

      如果一個進程具有超級用戶特權,則大多數文件權限檢查都不再進行。

      組 ID

      口令文件登錄項也包括用戶的組 ID(group ID),它是一個數值。

      組 ID 也是由系統管理員在指定用戶登錄名時分配的。

      這種機制允許同組的各個成員之間共享資源。

      附屬組 ID

      除了在口令文件中對一個登錄名指定一個組 ID 外,大多數 UNIX 系統版本還允許一個用戶屬于另外一些組。

      讀文件 /etc/group,尋找列有該用戶作為其成員的前16 個記錄項就可以得到該用戶的附屬組 ID(supplementary group ID)。

      1.9 信號

      信號用于通知進程發生了某種情況。

      進程有 3 種處理信號的方式:

      忽略信號

      有些信號表示硬件異常,例如,除以 0 或訪問進程地址空間以外的存儲單元等,因為這些異常產生的后果不確定,所以不推薦使用這種處理方式。

      按系統默認方式處理

      對于除數為 0,系統默認方式是終止該進程。

      提供一個函數,信號發生時調用該函數,這被稱為捕捉該信號

      通過提供自編的函數,我們就能知道什么時候產生了信號,并按期望的方式處理它。

      終端鍵盤上有兩種產生信號的方法:

      中斷鍵(interrupt key):Delete 或 Ctrl + C

      退出鍵(quit key):Ctrl + \

      它們被用于終端當前運行的進程。

      另一種產生信號的方法是調用 kill 函數,在一個進程中調用此函數就可向另一個進程發送一個信號。這樣做的限制是:當向一個進程發送信號時,我們必須是那個進程的所有者或者是超級用戶。

      1.10 時間值

      歷史上,UNIX 系統使用兩種不同的時間值:

      日歷時間:

      自協調世界時(Coordinated Universal Time,UTC)1970 年 1 月 1 日 00:00:00 這個特定時間以來所經歷的秒數累計值。

      系統基本數據類型 time_t 用于保存這種時間值。

      進程時間:

      也被稱為 CPU 時間,用以度量進程使用的中央處理器資源。進程時間以時鐘滴答計算。

      系統基本數據類型 clock_t 用于保存這種時間值。

      當度量一個進程的執行時間時,UNIX 系統為一個進程維護了 3 個進程時間值:

      時鐘時間

      又稱為墻上時鐘時間(wall clock time),它是進程運行的時間總量,其值與系統中同時運行的進程數有關。

      用戶 CPU 時間

      是執行用戶指令所用的時間量。

      系統 CPU 時間

      是為該進程執行內核程序所經歷的時間。

      取得任一進程的三個時間值命令:time(1)

      1.11 系統調用和庫函數

      所有的操作系統都提供多種服務的入口點,由此程序向內核請求服務,這些入口點被稱為系統調用。

      UNIX 所使用的技術是為每個系統調用在標準 C 庫中設置一個具有同樣名字的函數。用戶進程用標準 C 調用序列來調用這些函數,然后,函數又用系統所要求的技術調用相應的內核服務。

      通用庫函數可能會調用一個或多個內核的系統調用,但是它們并不是內核的入口點。

      系統調用通常提供一種最小接口,而庫函數通常提供比較復雜的功能。

      習題

      在 1.7 節中, perror 的參數是用 ISO C 的屬性 const 定義的,而 strerror 的整形參數沒有用此屬性定義,為什么?

      strerror 函數定義:

      #include char *streror(int errnum);

      perror 函數定義:

      #include void perror(const char *msg);

      strerror 傳遞的參數為 int 類型,傳遞的是值,因此不會修改原來參數的值。

      perror 傳遞的參數為 const char * 類型,傳遞的是對應的地址,如果不使用 const 限定的話,那么如果在函數內修改了值,函數外的變量值也會變化。

      若日歷時間存放在帶符號的 32 位整型數中,那么到哪一年它將溢出?可以用什么辦法擴展溢出浮點數?采用的策略是否與現有的應用相兼容?

      32 位整型數的最大值為 2147483647 ,大概為 68.09626 年,最大可表示到 2038-01-19 11:14:07。

      將 time_t 數據類型定為 64 位整型。

      如果它現在是 32 位整型,那么為使應用程序正常工作,應當對其重新編譯。

      但是,某些文件系統及備份介質以 32 位整型存放時間。對于這些同樣需要加以更新,但又需要能讀舊的格式。

      若進程時間存放在帶符號的 32 位整型數中,而且每秒為 100 時鐘滴答,那么經過多少天后該時間值將會溢出?

      大約 248 天。

      Linux Unix

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:數據協作系統(2分鐘之前已更新)
      下一篇:excel多張表格建立工作組的方法步驟(excel中怎么創建多個組)
      相關文章
      亚洲国产高清视频在线观看| 亚洲人成www在线播放| 全亚洲最新黄色特级网站 | 亚洲国产精品专区在线观看| 亚洲AV永久无码天堂影院 | 亚洲精品伊人久久久久| 亚洲国产高清在线精品一区| 亚洲视频欧洲视频| 亚洲精品456在线播放| 亚洲av无码乱码国产精品| 亚洲AV一宅男色影视| 亚洲成A人片在线观看WWW| 亚洲AV无码成人精品区在线观看 | 亚洲最大的黄色网| 亚洲一区欧洲一区| 亚洲另类自拍丝袜第1页| 亚洲一级毛片在线播放| 亚洲日本va在线观看| 亚洲一区AV无码少妇电影| 亚洲精品无码成人| 内射无码专区久久亚洲| 亚洲一级Av无码毛片久久精品| 精品亚洲一区二区三区在线播放| AV在线播放日韩亚洲欧| 在线a亚洲v天堂网2019无码| 亚洲国产精品无码久久久秋霞2| 亚洲国产精品婷婷久久| 亚洲视频一区二区在线观看| 亚洲大片免费观看| 亚洲色偷偷偷综合网| 国产成人精品日本亚洲语音| 亚洲成a人一区二区三区| 国产精品亚洲美女久久久| 国产亚洲综合一区柠檬导航| 亚洲嫩草影院久久精品| 亚洲另类春色国产精品| 亚洲国产综合AV在线观看| 亚洲精品tv久久久久| 亚洲综合国产一区二区三区| 午夜影视日本亚洲欧洲精品一区| 亚洲成人网在线观看|