Linux下基礎I/O

Lin9ux下的基礎I/O

C語言階段

  1. 在學習C語言的時候,我們要實現程序的I/O操作,需要調用fopen()和fclose來打開和關閉文件,fopen()成功返回FILE*的文件指針,
  2. 利用fread和fwrite函數來進行文件的讀寫操作。當然我們還學過fseek重置文件指針,ftell,rewind等函數
  3. 我們還知道,C會默認打開流,stdin,stdout,stderr,並且這三個流都是FILE*類型的,即文件指針。

系統編程階段

  1. 當我們進入系統編程之後,我們可以同樣的調用系統接口,來實現I/O操作。
    系統接口

  2. open
    int open(const char*pathname, int flags);
    int open(const char* pathname,int flags,mode_t mode)
    pathnamm:要打開文件名稱
    flag:O_RDONLY(只讀),O_WRONLY(只寫),O_RDWR(可讀可寫),O_CREAT(文件不存在則創建之,並且要加上mode權限)
    3.write
    ssize_t write(int fd, const void *buf, size_t count);
    fd:對應操縱文件的文件描述符,
    buf:源數據存放內存
    count:一次寫入多少個字節
    返回值:實際寫入字節數

  3. read
    ssize_t read(int fd, void *buf, size_t count);
    fd:對應文件的文件描述符;
    buf:寫到的目的內存;
    count:一次寫入的字節數;
    返回值:實際讀取的字節數

  4. close
    int close(int fd);
    關閉對應文件描述符爲fd的文件。
  5. 我們知道,c提供的f#類函數都是庫函數,調用成功返回文件指針,而open,close,write,read屬於系統調用接口,在講操作系統的作用的時候,講過下面這張圖。
    這裏寫圖片描述
  6. 不難看出,c庫函數都是封裝了系統調用的接口,方便二次開發。我們又知道linux下一個進程的PCB中有files*的一個字段,描述一個進程打開文件的情況,而這個指針指向一個files_struct的結構體表,這個表中最重要的就是保護一個指針數組,每個數組元素都指向打開的文件,我們通常就利用數組的下標來操縱對應位置的元素,我們把這裏的下標稱之爲文件描述符,我們都知道數組下標從0開始的,所以每一個進程都默認打開0,1,2三個文件描述符表示的文件,分別代表標準輸入,標準輸出,標準出錯。如下圖這裏寫圖片描述
    這裏我們就來練習一下這幾個函數:
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<sys/types.h>
  4 #include<string.h>
  5 #include<fcntl.h>
  6 #include<sys/stat.h>
  7 int main()
  8 {        
  9          
 10     int fd=open("myfile",O_RDWR|O_CREAT,0644);
 11     if(fd<0)
 12     {    
 13         perror("open");
 14         return -1;
 15     }    
 16     int count=5;
 17     char *buf="hello,world\n";
 18     while(count--)
 19     {    
 20 write(fd,buf,strlen(buf));
 21     }    
 22     char buf2[1024];
 23     while(1)
 24     {    
 25          
 26         ssize_t s=read(fd,buf2,strlen(buf)-1);                                                                                                                                                               
 27         if(s>0)
 28         {
 29             printf("myfile if :%s\n",buf2);
 30         }
 31         else
 32         {
 33             break;
 34         }
 35     }    
 36     close (fd);
 37     return 0;
  • 既然現在我們瞭解了系統編程的I/O函數,已經文件描述符的概念,我們就知道,一個進程默認會打開0,1,2三個分別代表標準輸入,標準輸出,標準出錯的文件描述符,而系統默認的輸出就是屏幕,默認的輸入就是鍵盤,如果講原本輸出到屏幕的數據輸出到指定地方,這就叫做輸出重定向.就拿輸出重定向來舉例,printf()默認是往屏幕上面打印數據,再調用時,底層就會找到1號文件描述符,我們只需要關閉1號文件描述符,然後用我們創建的myfile代替他,以後調用printf()函數就會找到1號文件描述符對應的內容,即往myfile中輸出數據,

我們來實現一個小程序,使原來往屏幕上打印的數據,輸出到文件中。

  1 #include<stdio.h>                                                         
  2 #include<unistd.h>
  3 #include<sys/types.h>
  4 #include<string.h>
  5 #include<fcntl.h>
  6 #include<sys/stat.h>
  7 int main()
  8 {
  9 close(1);
 10 int fd=open("myfile",O_RDWR|O_CREAT,0644);
 11 if(fd<0) 
 12 {        
 13     perror("open");     
 14     return -1;          
 15 }        
 16          
 17 printf("how are you?\n");
 18 close(fd);
  }     

這裏寫圖片描述
原本輸出到屏幕上的數據就被輸出到文件裏面了


FILE結構和文件描述符

  1. 因爲IO函數和系統調用對應,所以本質上還是操控的是文件描述符。所以再FILE結構體裏面肯定封裝了文件描述符。
  2. 一般的C庫函數寫入文件都是全緩衝的,寫入顯示器是行緩衝的。
  3. 而我們的系統調用接口是沒有自帶緩衝區的。

靜態庫和動態庫

  1. 要了解靜態庫和動態庫首先我們來了解一下文件系統,來看一下文件系統,每一個當我們使用ls -l 選項列出文件信息的時候,能看到文件的模式,硬鏈接數,文件所屬者和所屬組,當然還有文件大小和文件最後被修改時間,以及文件名。

  2. 但是每一個文件再計算機中如何存儲的,我們來看下面這張圖
    這裏寫圖片描述
    超級快:保存着文件系統本身的結構信息。
    i節點表:存放着文件的屬性,如大小,所有者,最後修改時間
    數據區:存放着文件的內容

  3. 在查找一個文件的時候,並不是利用文件名來找,而是用文件名對應的inode(其實在linux中一個inode可以對應多個inode,)

  4. 我們可以使用ln命令來使兩個文件對應同一個inode。這裏寫圖片描述
  5. 我們可以看出, 1 和 2 文件的 元信息中有 一列變成了2.
  6. 我們把通過inode引用另外一個文件叫做硬鏈接,把通過文件名引用另一個文件叫做軟鏈接

靜態庫

程序在編譯鏈接的過程中,把庫的代碼全部鏈接到可執行文件中,運行期間不需要靜態庫,這樣造成可執行文件太大,並且效率低。
靜態庫命名規則 libXXX.a(lib是前綴,.a是後綴,XXX是庫名)

生成方法

  1. 先使用gcc -c選項使目標文件在彙編完成後結束生成.o文件
  2. 使用ar -rc 庫名 目標文件 來生成動態庫
    . 這裏寫圖片描述

鏈接方法

  1. gcc man.c -L . -l mymath
    -L選項後面加上庫的路徑,-l選項後加上庫名,注意刪除掉前綴後綴
    這裏寫圖片描述

動態庫

程序在運行期間纔回去鏈接到動態庫的代碼,多程序 共享使用庫的代碼。一個動態庫鏈接的可執行程序僅僅包含它用到的函數的入口地址,而不是外部函數所在目標文件的整個機器碼。節省了資源規則:libXXX.so
動態庫命名

生成方法

gcc -shared表示生成共享庫格式
gcc -fPIC表示生成位置無關的碼
這裏寫圖片描述

鏈接方法

gcc man.c -L . -l mymath

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