APUE 讀書筆記(一)

應老大要求,從今天開始APUE的讀書筆記。其實就是一些比較需要注意的點

第一章. UNIX基礎知識

   一、登陸

拿到一臺Linux主機,最新開始的是登陸。

Linux 登陸的驗證是靠 /etc/passwd 這個文件的。

$ grep kiosk /etc/passwd
kiosk:x:1000:1000:kiosk:/home/kiosk:/bin/bash

這些子段分別是用戶名,加密後的密碼,用戶id,用戶組id,描述,家目錄,使用的shell。

整個登陸過程如下:

      read /etc/inittab                    get username in tty             get password

init ---------------------> mingetty ---------------------------> login ------------------/etc/pam.d-----------> call PAM modules -------------> act/rej

Linux PAM是一個通用的認證機制,是以庫的模式。

二、文件和目錄

文件系統:

            目錄(directory)是一個包含目錄項的文件,在邏輯上,可以認爲每個目錄項都包含一個文件名,同時還包含說明該文件屬性的信息。文件屬性是:文件類型,文件長度,文件所有者,文件的許可權(例如,其他用戶能否能訪問該文件),文件最後的修改時間等,可以使用stat和fstat去查看詳細信息。

使用stat命令去查看文件的詳細信息。

$ stat google-chrome.desktop 
  File: ‘google-chrome.desktop’
  Size: 8392      	Blocks: 24         IO Block: 4096   regular file
Device: fd02h/64770d	Inode: 134751621   Links: 1
Access: (0755/-rwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2018-03-19 15:06:39.280035865 +0800
Modify: 2018-03-08 17:50:18.060889472 +0800
Change: 2018-03-08 17:50:26.282852535 +0800
 Birth: -

解釋一下:

- File:顯示文件名
- Size:顯示文件大小
- Blocks:文件使用的數據塊總數
- IO Block:IO塊大小
- regular file:文件類型(常規文件)
- Device:設備編號
- Inode:Inode號
- Links:鏈接數
- Access:文件的權限

- Gid、Uid:文件所有權的Gid和Uid。

三、輸入和輸出

首先清楚文字描述符的概念。

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

        按慣例,每當運行一個新程序時,所有的 s h e l l都爲其打開三個文件描述符:標準輸入、標準輸出以及標準出錯。如果像簡單命令 l s那樣沒有做什麼特殊處理,則這三個描述符都連向終端。

         文件描述符的本質是 數組元素的下標。


            右側的表稱爲i節點表,在整個系統中只有1張。該表可以視爲結構體數組,該數組的一個元素對應於一個物理文件。

           中間的表稱爲文件表,在整個系統中只有1張。該表可以視爲結構體數組,一個結構體中有很多字段,其中有3個字段比較重要:

           左側的表稱爲文件描述符表,每個進程有且僅有1張。該表可以視爲指針數組,數組的元素指向文件表的一個元素。最重要的是:數組元素的下標就是大名鼎鼎的文件描述符。

           open系統調用執行的過程:新建一個i節點表元素,打開的物理文件(如果對應於該物理文件的i節點元素已經建立,就不做任何操作);新建一個文件表的元素,根據open的第2個參數設置file status flags字段,將current file offset字段置0,將v-node ptr指向剛建立的i節點表元素;在文件描述符表中,尋找1個尚未使用的元素,在該元素中填入一個指針值,讓其指向剛建立的文件表元素。最重要的是:將該元素的下標作爲open的返回值返回。

   不帶緩存的IO和標準IO

       不帶緩存的IO是指 函數open、read、write、lseek以及close提供了不用緩存的 I / O。這些函數都用文件描述符進行工作。   如read和write函數都有一個參數--- ‘buf’。這個參數用來指向讀取或者寫入的地方。通常我們都是自己新建一個數組,用來讀取或者寫入,這就是不帶緩存的IO,需要自己考慮讀取內容的存放位置(或者寫入內容的存放位置),同時還得考慮讀取或者寫入的長度。

     與之相對的就是標準IO。最常見的是printf()。

四、進程控制

     有三個用於進程控制的主要函數: fork、exec和waitpid(exec函數有六種變體,但經常把它們統稱爲exec函數)。

首先看下面的代碼

#include <sys/types.h>
#include <sys/wait.h>
#include "ourhdr.h"
#include "myerror.h"

int main(void){
    char buf[MAXLINE];
    pid_t pid;
    int status;

    printf("%% ");
    while(fgets(buf,MAXLINE,stdin) != NULL) {
        buf[strlen(buf) - 1] = 0;  /*replace newline with null*/
        if ((pid=fork()) < 0)
           err_sys("fork error");

        else if (pid == 0) {       /*child*/
           execlp(buf,buf,(char *) 0);
           err_ret("couldn't execute: %s",buf);
           exit(127);
        }

        if ((pid = waitpid(pid,&status,0)) < 0)  /*parent*/
           err_sys("waitpid error");
        printf("%% ");
    }
    exit(0);
}

          調用fork創建一個新進程。新進程是調用進程的複製品,故稱調用進程爲父進程,新創建的進程爲子進程。 fork對父進程返回新子進程的非負進程ID,對子進程則返回0。因爲fork創建一新進程,所以說它被調用一次 (由父進程),但返回兩次(在父進程中和在子進程中 )。

         在子進程中,調用 execlp以執行從標準輸入讀入的命令。這就用新的程序文件替換了子進程。fork和跟隨其後的exec的組合是某些操作系統所稱的產生一個新進程。

         子進程調用 execlp執行新程序文件,而父進程希望等待子進程終止,這一要求由調用waitpid實現,其參數指定要等待的進程 (在這裏, pid參數是子進程 I D )。waitpid函數也返回子進程的終止狀態( status變量)。在此簡單程序中,沒有使用該值。如果需要,可以用此值精確地確定子進程是如何終止的。

$ ./a.out 
% date
2018年 03月 19日 星期一 17:24:24 CST
% pwd
/home/kiosk/C/apue
% 

五、UNIX時間值

UNIX中有三個時間值。

時鐘時間,用戶cpu時間,系統cpu時間。

時鐘時間(牆上時鐘時間wall clock time):從進程從開始運行到結束,時鐘走過的時間,這其中包含了進程在阻塞和等待狀態的時間。

用戶CPU時間:就是用戶的進程獲得了CPU資源以後,在用戶態執行的時間。

系統CPU時間:用戶進程獲得了CPU資源以後,在內核態的執行時間。

進程的三種狀態爲阻塞、就緒、運行。

   時鐘時間 = 阻塞時間 + 就緒時間 +運行時間
   用戶CPU時間 = 運行狀態下用戶空間的時間

   系統CPU時間 =  運行狀態下系統空間的時間。

$ time grep "_POSIX_SOURCE" /usr/lib64/*.h &> /dev/null

real	0m0.004s
user	0m0.003s
sys	0m0.001s



發佈了146 篇原創文章 · 獲贊 94 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章