Linux中man手冊,阻塞和非阻塞,stat,文件操作和遍歷,文件描述符複製dup()



簡 述: 講解在 Unix / Linux 下,man 手冊的使用;寫了一個例子調用系統庫函數來讀寫文本文件,和打印文件描述符;阻塞和非阻塞實際是文件的屬性,而非標準輸入輸出的 I/O 函數的屬性。 以及文件詳細描述的 stat 命令和 stat() 函數的使用;文件屬性相關的操作;文件夾遍歷和創建、刪除的相關函數,可能 Linux 有時候會調用到他們,現在實際上,更多的使用 Qt 的庫來對文件進行讀寫操作;以及關於複製文件描述符的函數 dup() 函數的講解


編程環境:

💻: uos20 📎 gcc/g++ 8.3 📎 gdb8.0

💻: MacOS 10.14 📎 gcc/g++ 9.2 📎 gdb8.3


man 手冊的使用:

  • man 2 open 在第二章裏面,精確查找 open 函數

  • man man 查看 man 手冊的大致介紹 (Linux 下)

  • mac 下安裝中文 man 文檔:Mac配置中文 man 手冊


系統函數讀寫文件:

如下爲 Unix / Linux系統的庫函數:

  • open() :打開文件

  • read() :對文件進行讀操作

  • write() :對文件進行寫操作

  • lseek() :移動文件指針;擴展文件大小(移動指針後,要進行一次寫操作)

    • 文件指針移動到頭部:lseek(fd, 0, SEEK_SET);

    • 文件指針移動到尾部:lseek(fd, 0, SEEK_END);

    • 文件指針移動到當前位置:lseek(fd, 0, SEEK_SUR);

    • 文件大寫爲 100K, 擴展到 1000K:

      lseek(fd, 1000, SEEK_END);    //文件指針從文件尾部偏移 1000 大小,這部分用^@ 填充佔位
      wrire(fd, "a", 1);            //隨便寫一個什麼到文件中,進行一次寫操作
      
  • 全局變量 errno :對於調用系統函數對文件進行讀寫操作,函數會返回一個錯誤 int 類型的數值。而 errno 變量就是不同的錯誤返回值的含義打印出來(字符串),使得人類可以看懂。調用方法: perror("[註釋信息: ]");


寫一例子:

  • Linux 系統的函數,調用 openprintfread 寫一個例子:

  • 編寫代碼如下:

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <errno.h>
    
    int main()
    {
        int fp = open("hello.txt", O_RDWR);
        int fp2 = open("temp.txt", O_WRONLY | O_CREAT, 0777);  //創建文件時候,必須要有權限
        printf("fp = %d\n", fp);
        printf("fp2 = %d\n", fp2);
    
        if (fp == -1)
            perror("[註釋信息: ]");  //如果返回錯誤,會打印人類可讀懂的出字符串
    
        char buf[4096];
        int len = read(fp, buf, sizeof(buf));
    
        while (len > 0)
        {
            int ret = write(fp2, buf, len);
            len = read(fp, buf, sizeof(buf));
            printf("ret = %d\n", ret);
        }
    
        close(fp);
        close(fp2);
    
        return 0;
    }
    
  • 編譯:g++-9 main.cpp -o main

  • 運行:其中 fp 便是打開文件 hello.txt 的文件描述符(因爲 0、1、2 被 stdin、stdout、stdout 佔了,所以最小就是 3);然後當打開第二個文本文件 temp.txt 的時候,其返回的文件描述符自然就是 4。關於文件描述符,詳細原理解釋可參考 此篇

源碼下載: 07_sysfun


阻塞和非阻塞:

終端程序: bash 爲前臺程序,當執行 a.out 程序時候,bash 就成爲了後臺程序,a.out 成爲了前臺程序(代碼執行到,等待輸入);當鍵盤輸入完成,a.out 成爲了後臺程序,bash 成爲了前臺程序。

當輸入的長度 大於 buf[10] 中的 10 時候, 多餘的部分就會成爲後面的命令輸入。

將下面的兩種,手動敲一遍。

阻塞非阻塞 情況下,是文件的屬性,而非標準輸入輸出的 I/O 函數的屬性。

  • 普通文件:hello.cpp

    • 默認是非阻塞
  • 終端設備 /dev/tty (默認是阻塞)

    • 終端
    • 管道
    • 套接字

stat / lstat 函數 :

  • 寫一個小的程序,判斷 ls -l 命令,基本可以實現 改用 switch()

  • lstatstat 函數對於鏈接 l 的區別不一樣。

    • lstat 讀取的是鏈接文件, 本身的屬性
    • stat 讀取的是鏈接文件指向的文件的屬性 (也被稱呼:追蹤,穿透)
    • fstat 第一個參數是指文件描述符

#對應的 stat 命令:

作用:顯示文件或文件系統的狀態

uinx: stat -x hello.txt

linux: stat hello.txt


運行命令可以看到:hell.txt 文件的所有信息


ls -l hello.txt 查看看的,前面的 -rwxrwxrwx 就是表示下圖的 文件類型文件所有者權限文件所屬組權限其他人對該文件的權限


  • 其用 含義就是如下:
  • 其在代碼裏面,用 struct 所表示的爲:
st_ mode -- 16位整數
  0-2 bit--其他人權限
      - S_IROTH  00004    讀權限
      - S_IWOTH  00002    寫權限
      - S_IXOTH  00001    執行權限
      - S_IRIvxO 00007    掩碼,過濾 st_mode 中除其他人權限以外的信息
    
  3-5 bit --所屬組權限
      -S_IRGRP   00040    讀權限
      -S_IWGRP   00020    寫權限
      -S_IXGRP   00010    執行權限
      -S_IRWXG   00070    掩碼,過濾 st_mode 中除所屬組權限以外的信息
  
  6-8 bit --文件所有者權限
      -S_IRUSR   00400    讀權限
      -S_IWUSR   00200    寫權限
      -S_IXUSR   00100    執行權限
      -S_IRWXU   00700    掩碼,過濾 st_mode 中除文件所有者權限以外的信息。
  
  12-15 bit --文件類型
      -S_IFSOCK  0140000  套接字
      -S_IFLNK   0120000  符號鏈接(軟鏈接)
      -S_IFREG   0100000  普通文件
      -S_IFBLK   0060000  塊設備
      -S_IFDIR   0040000  目錄
      -S_IFCHR   0020000  字符設備
      -S_IFIFO   0010000  管道
      -S_IFMT0   0017000  掩碼,過濾 st_mode 中除文件類型以外的信息
      
  
 // 命令對應的函數 
int stat(const char *path, struct stat *buf);
int Istat(const char *path, struct stat *buf);

文件屬性相關的函數:

  • access() 判斷傳入的文件,所具有的(讀、寫、執行、是否存)的權限
  • chmod() 修改文件權限
  • chown() 修改文件所有者和所屬組
  • truncate() 修改文件大小
  • ^@ 文件空洞, 填充佔位符號,實際就是 \0

目錄操作相關函數:

目錄操作相關函數:

  • rename() 文件重命名
  • chdir() 修改 當前進程(應用程序)的路徑;cd
  • getcwd() 獲取當前進程的工作目錄;pwd
  • mkdir() 創建目錄;mkdir
  • rmdir() 刪除一個空目錄;rm

目錄遍歷相關函數:

  • opendir() 打開一個目錄
  • readdir() 讀目錄(進入子目錄,需要手動創建遞歸函數)
  • close() 關閉目錄

dup / dup2 / fcntl 函數:

  • dup() 複製文件描述符
  • dup2() 同上,形參不同(也會稱爲 參數 2:文件描述符的重定向)
  • fcntl() 修改文件的狀態標誌

下載地址:

https://github.com/xmuli/linuxExample

歡迎 star 和 fork 這個系列的 linux 學習,附學習由淺入深的目錄。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章