1. 程式人生 > >linux高階程式設計——IO

linux高階程式設計——IO

 

 

1,檔案IO

   1)open——開啟或建立一個檔案

    open(char *,flag,mode)在fcntl.h檔案中宣告。

    引數:

    char *  包含有檔名和路徑

    flag   開啟檔案方式

    mode  建立檔案的許可權

    

    flag 內容

flag 功能
O_RDONLY 只讀
O_WRONLY 只寫
O_RDWR 讀寫
   
O_CREAT 建立一個檔案
O_EXCL 如果使用O_CREAT是檔案存在,則可返回錯誤訊息。這一引數可測試檔案是否存在
O_TRUNC 開啟檔案(會刪除已存在的內容)
O_APPEND 追加方式開啟檔案(不會刪除已存在的內容)

    許可權:檔案許可權 == mode&(~umask)

 返回值:

    成功:檔案描述符(在一個程序中,為了區別每個檔案),非負正整數,即檔案的ID號;

    出錯:-1;  

 

2)write————寫

  write (int fd,void *buf,size t count);

  引數:

    fd  向哪個檔案去寫

    *buf 寫什麼內容

    t   寫多少個

  返回值:

    實際寫的位元組數

 

3)read————讀  

  read (int fd,void *buf, size t count)

  引數:

    fd  從哪個檔案去讀

    *buf 讀什麼內容

    t   讀多少個

  

  返回值:

    實際讀的位元組數

4)close————關閉檔案

    close(fd);

——————————————————————————————————————————————————————————————————

 

——————————————————————————————————————————————————————————————————

5)  lseek ————調整讀寫位置指標

  lseek(int fd,off_t offset,int whence);

  標頭檔案:sys/types.h    unist.h;

  引數:

    fd : 要調整的檔案的檔案描述符

     offset : 偏移量,每一讀寫操作所需要移動的距離,單位是位元組的數量,可正可負;

    whence :  當前位置的基點,有三個標誌:

        SEEK_SET    :  當前位置為檔案的開頭,新位置為偏移量的大小(後移為正,前移為負)

        SEEK_CUR   :     當前位置為檔案指標的位置,新位置為當前位置加偏移量

        SEEK_END   :   當前位置為檔案的結尾,新位置為檔案大小加偏移量的大小

  返回值:

      成功:檔案當前的位置

      出錯:-1

 

 

 ******************************************************************************************************************************************************************************

 

 

檔案IO:是直接呼叫核心提供的系統呼叫函式,標頭檔案:unistd.h

標準IO:是間接點用系統呼叫函式,標頭檔案: stdio.h

 

三個快取:

1,程式中的快取,就是你想從核心讀寫的快取(陣列)——使用者空間的快取

2,每開啟一個檔案,核心在核心空間中也會開闢一塊快取,——核心空間快取

    檔案IO的 寫  ——> 將使用者空間的快取寫到核心空間的快取中

    檔案IO的 讀  ——>將核心空間的快取讀到使用者空間的快取

3,標準IO的庫函式中也有一個快取 ——  庫快取

 

 

 

2,標準IO

     printf滿足一定條件才能將庫快取的內容寫到核心:遇到\n;庫快取寫滿時,會呼叫系統呼叫函式。(庫快取為1024位元組)

1)fopen    開啟

2)  fclose    關閉  ,在關閉之前重新整理快取區,強制寫入核心

3)  fseek,rewind   位置指標 

 

4)   讀寫函式較多(分三類:全快取,行快取,無快取)

 

 

1) FILE *fopen (const char *path , const char *mode);                建立一個檔案設定的許可權為666,生成檔案的許可權為 666&(~umask)

  返回值:FILE *    檔案流指標        類似於檔案IO中的檔案描述符

    FILE  定義 : struct_IO_FILE       在/usr/include/libio.h

            包含讀寫快取的首地址、大小、位置指標等

  標準的輸入流:stdin    0

  標準的輸出流:stdout  1

  標準的出錯流: stderr  2

  

  引數:path  檔案的位置

     mode     相當於檔案IO的flag      (char *    字串)

        b :  二進位制檔案

        r :  只讀方式開啟檔案,檔案必須存在

        w/a :   只寫方式開啟檔案,檔案不存在則建立;

                區別: w ==  O_TRUNC  ;  a  ==  O_APPEND  

        +  :    讀寫方式開啟檔案,檔案必須存在;

 

2)fcloes

3)讀寫函式

  1, 行快取    遇到新行符(\n) 或寫滿快取時,即呼叫系統呼叫函式

          讀: fgets,gets,printf,fprintf,sprintf

          寫: fputs,puts,scanf

  2,    無快取    只要使用者呼叫這個函式,就會將其內容寫到核心中

 

  3,全快取    只有寫滿快取再呼叫系統呼叫函式

          讀 :fread

          寫 :fwrite    

 

 

 

      3.1    行快取的讀寫函式fgets, fputs

      char *fgets (char *s,int size , FILE *stream);

      引數:

        s :      快取,即讀到哪裡去

        size :     讀多少位元組

        stream  :  從什麼地方讀

      返回值:

        成功: s (快取的地址)

        已處於檔案尾端或出錯: null

      

      int fputs (const char *s,FILE *stream);

      引數:

        s :      快取。即寫什麼內容

        stream  :  寫到哪裡去

      返回值:

        成功:非負值

        出錯:EOF   -1

    3.2 fflush(FILE *fp)

    把庫函式的快取內容強制寫入核心(在fclose 中包含)

    3.3  無快取: stderr

      stdout   行快取

    3.4 調整位置指標

      fseek()

      引數與lseek()一致,但返回值不同

      返回值:

          成功:0

          失敗:-1

 

      rewind(FILE *fp) 用於設定流的檔案位置指示為檔案開始,該函式呼叫成功無返回值。

        rewind()  ==    (void) fseek(fp 0,SEEK_SET);

      

      ftell(FEIL *fp)

          用於取得當前的檔案位置,呼叫成功則為當前檔案位置指示,出錯則為 -1L;

   3.5  行快取的讀寫函式 gets , puts 

    char *gets (char *s);

    int puts (const char *s);

      

    gets 與  fgets 的區別:

       gets() 時不能指定快取的長度,可能造成快取越界,寫到快取之後的儲存空間,產生不可預料的後果;

       gets()只能從標準輸入中讀;

       gets() 並不將新行符存入快取,fgets()將新行符存入快取;

 

    puts 與 fputs 的區別:

        puts()只能向標準輸出中寫;

        puts() 輸出是會新增一個新行符,fputs() 不會新增;

 

   3.6    fprintf, printf, sprintf             行快取的函式

      int fprintf (FILE *stream,"字串格式")

        fprintf  可以輸出到檔案中,也可以輸出到顯示器        eg: fprintf(fp,"hello linux");

        printf   只能輸出到顯示器

      int sprintf (str *,"字串格式")

        輸出內容到一個字串中                   eg: char buf[128] = 0;   sprintf (buf,"hello linux");

  3.7    一個字元的讀寫函式

      int fgetc(FILE *fp)        將檔案中的內容一個字元的輸出到顯示器,到檔案結尾時返回EOF

          功能: 從檔案讀取一個字元

          引數: 檔案流

          返回值: 正確為讀取到的字元;到檔案結尾或出錯時返回EOF

        

      int fputc(int c, FILE *fp)      輸入一個字元到檔案中,成功則返回輸入的字元,出錯則返回EOF

          功能:寫一個特字元到檔案中

          引數:第一個引數為要寫的字元,第二個為檔案流

          返回值: 正確為返回輸入的字元,出錯返回EOF

 

      fputs 有快取,但不是行快取

——————————————————————————————————————————————————————————————————————————————

——————————————————————————————————————————————————————————————————————————————

 3.8   feof       判斷受否已經到檔案結尾

    int feof (FILE *stream);

    引數:檔案流

    返回值:檔案結束,返回非0;沒有則返回0;

3.9    ferror    判斷是否讀寫錯誤

    int derror (FILE *stream);

    引數:檔案流

    返回值: 是讀寫錯誤,返回非0;不是則返回0;

3.10  clearerr   清除流錯誤

    void clearerr (FILE *stream);

    引數:檔案流

————————————————————————————————————————————————————————————————————————————————

————————————————————————————————————————————————————————————————————————————————

     全快取

    fread 和 fwrite    全快取的讀寫函式

  size_t fread (void *ptr ,size_t size,size_t nmemb,FILE *stream);

  size_t fwrite (const void *ptr,size_t size,xize_t nmemb,FILE *stream);

  引數:

      ptr:      寫的內容

      size:      寫的內容中,每一個單元所佔的位元組數

      nmemb:    寫的內容中,有多少個單元

      stream:              寫到哪裡去

 

      總共所寫的位元組:size * nmemb

      返回值: 實際讀寫的單元數

 

linux下靜態庫和動態庫的製作與使用

  • 靜態庫

      libxxx.a , 在編譯時就將庫編譯進可執行程式中。

      優點:程式的執行環境中不需要外部的函式庫

      缺點:可執行程式大

  • 動態庫

      又稱共享庫,libxxx.so ,在執行時將庫載入到可執行程式中。

      優點:可執行程式小

      缺點:程式的執行環境中必須提供相應的庫。

 

  函式庫目錄:/lib           /usr/lib    

 

  靜態庫的製作:

    1,生成目標檔案:gcc  -c  file.c

    2,靜態庫建立命令  ar

        ar -cr  libfile.a  file.o

          -c  :  create

          -r  :replace ,表示當插入的模組 file.o 已經存在 libfile.a 中,則覆蓋。反之 ar 顯示一個錯誤訊息

 

    1)由原始檔生成目標檔案  gcc -c -o sub.o sub.c

    2)把目標檔案生成靜態庫  ar -cr -o libsub.a sub.o

    3)  gcc -o  a  main.c -L. -lsub      . 代表當前目錄;-lcub 預設libxxx.o

 

  動態庫製作:

    1,生成目標檔案 :gcc  -c -o file.c

    2,gcc  -shared -fpic -o libfile.so file.o

          -fpic :   產生位置無關程式碼

          -shared: 生成共享庫。

      用上述命令生成 libsub.so 動態函式庫

      gcc -o out main.c -L. -lsub

      此時還不能直接 ./out  ,因為在動態函式庫使用時,會查詢/usr/lib   /lib  目錄下的動態函式庫,而此時生成的庫還不在裡邊

      

      解決方法:

        1) 把  libsub.so  放到 /usr/lib   /lib 中去

        2)假設  libsub.so  在/home/linux/file 中        環境變數的方式

               export LD_LIBRARY_PATH = /home/linux/sddsub

               LD_LIBRARY_PATH

        3)  在 /etc/l.so.conf 檔案中加入生成庫的路徑,然後 /sbin/ldconfig

             /etc/ld.so.conf 時非常重要的一個目錄,裡面存放的時連結器和載入器搜尋共享庫時要檢查的目錄,預設是從 /usr/lib   /lib  中讀取,所以可以把庫的目錄假如這個檔案並執行  /sbin/ldconfig

 

目錄IO

      #include <sys/types.h>

      #inlcude <dirent.h>

目錄IO 檔案IO

opendir  只能開啟目錄

mkdir    建立目錄

open
readdir   讀目錄 read

rewinddir      調整指標位置

telldir

seekdir

rewind

ftell

fseek

closedir        關閉目錄

close

    1,opendir

      DIR *opendir (const char *pathname);

      引數:開啟的目錄及路徑

      返回值: 成功返回目錄流指標,出錯返回NULL

 

      int  mkdir (const char * path ,mode_t mode )

        path:      為想建立的目錄檔案路徑

        mode:    為該目錄的訪問許可權

        返回值:若目錄建立,則返回0;否則-1;

        生成的目錄許可權仍和umask有關

    2,readdir

      struct dirent *readdir (DIR *dr)

      引數:目錄流指標

      返回值:成功 則為 struct  dirent  指標,瑞在目錄尾或出錯則返回NULL

      struct dirent 定義在標頭檔案 dirent.h中

      此結構至少包括下列兩個成員:

      struct dirent

        {

            ino_t d_ino ;  // inode 號  

            char d_name[NAME_MAX+1];    //檔名

        }

     3,rewinddir:     重置讀取目錄的位置為開頭

       void rewinddir(DIR *dr);

       引數:目錄流指標

 

        long telldir(DIR *dirp)    讀取當前指標的位置

        引數:目錄流指標

        返回值:目錄流當前位置

        

        void seekdir(DIR *dirp,long loc);

        類似於檔案定位函式fseek(), 在目錄流上設定下一個 readdir() 操作的位置

        引數:目錄流指標和偏移量