《C程式設計語言》筆記 (八) UNIX系統介面

來源:互聯網
上載者:User

標籤:資料結構   掃描   儲存   沒有   類型   做了   設計   表示   sys   

8.1 檔案描述符
UNIX作業系統通過一系列的系統調用提供服務,這些系統調用實際上就是作業系統內的函數ANSI C標準函數庫是以UNIX系統為基礎建立起來的在UNIX系統中所有的外圍裝置都被看作是檔案系統中的檔案,因此,所有的輸入輸出都要通過檔案讀寫完成也就是說,通過一個單一的介面就可以處理外圍裝置和程式之間的所有通訊在讀寫檔案之前,必須先將這個意圖通知系統,該過程稱為開啟檔案如果是寫寫一個檔案,則可能需要先建立該檔案作業系統想程式返回一個小的非負整數,該整數稱為檔案描述符。任何時候對檔案的輸入輸出都是通過檔案描述符標識檔案,而不是通過檔案名稱標識檔案系統負責維護已開啟檔案的所有資訊,使用者程式只能通過檔案描述符引用檔案因為大多數的輸入輸出都是通過鍵盤和顯示器來實現的為了方便起見,UNIX對此做了特別的安排當命令解釋程式運行一個程式的時候,它將開啟3個檔案對應的檔案描述符分別是012 依次標識標準輸入 標準輸出 標準錯誤

  

8.2 低級IO --read和write

 

輸入輸出是通過read和write系統調用實現的在C語言中,可以通過函數read和write訪問這兩個系統調用read(int fd,char *buf,int n);write(int fd,char *buf,int n);第一個參數是檔案描述符第二個參數是程式中存放讀寫的資料的字元數組第三個參數是要傳輸的位元組數沒個調用返回實際傳輸的位元組數在讀檔案時,函數的傳回值可能會小於請求的位元組數如果傳回值為0,則標識已到達檔案結尾如果返回-1則表示發生了某種錯誤在寫檔案時傳回值是實際寫入的位元組數如果傳回值與寫入的位元組數不相等,則說明發生了錯誤在一次調用中,讀寫的資料可以為任意大小最常用的值為1,即每次讀寫1位元組(無緩衝)或是類似於1024或4096這樣的與外圍裝置的物理塊大小相應的值用更大的值調用該函數可以獲得更高的效率,因為系統調用的次數減少了#include "syscalls.h"main(){   char buf[BUFSIZ];   int n;   while((n = read(0,buf,BUFSIZ)) > 0)      write(1,buf,BUFSIZ);   return 0;}系統調用的函數原型集中放在一個syscalls.h中參數BUFSIZ也已經包含中標頭檔中對應所使用的作業系統來說,該值是一個較合適的數值如果檔案大小不是BUFSIZ的倍數,則對read的某次調用會返回一個較小的位元組數//getchar實現int getchar(void){   char c;   return (read(0,&c,1)==1)?(unsigned char) c : EOF;}其中c必須是一個char類型的變數,因為read函數需要一個字元指標類型的參數在返回語句中將c轉換為unsigned char類型可以消除符號擴充問題如果要在包含標頭檔<stdio.h>的情況下編譯getchar函數就必須用#undef預先處理指令取消getchar的宏定義因為在標頭檔中,getchar是以宏方式實現的

  

8.3 open creat close 和unlink
除了預設的標準輸入 標準輸出和標準錯誤檔案外其他檔案都必須在讀寫前顯式開啟系統調用open和creat用於實現該功能open和fopen很相似,不同的是 open非常一個檔案描述符 int類型的數值fopen返回一個檔案指標#include <fcntl.h>int fd;fd = open(char *name,int flags,int perms);參數name檔案名稱flags是一個int類型的值,說明檔案開啟檔案 包括         O_RDONLY  唯讀    O_WRONLY  唯寫    O_RDWR    讀寫目前 open 參數perms的值始終為0;如果開啟的檔案不存在則將導致錯誤可以使用creat系統調用建立新檔案或覆蓋已有的檔案int fd;fd = creat(char *name,int perms);如果建立成功返迴文件描述符 否則返回-1如果此檔案已存在,清空原來資料使用creat建立一個已經存在的檔案不會導致錯誤如果要建立的檔案不存在,以參數perms指定的許可權建立檔案每個檔案對應一個9位元的許可權資訊所有者所有者組其他成員一個程式同時開啟的檔案數是有限制的(通常為20)如果一個程式需要同時處理許多檔案,那麼他必須重用檔案描述符函數close用了斷開檔案描述符和已開啟檔案直接的串連,並釋放此檔案描述符close函數和標準庫中的fclose函數想對應,但它不需要清洗(flush)緩衝區如果程式通過exit函數退出或從主程式中返回,所有開啟的檔案將被關閉函數unlink將檔案從檔案系統中刪除,它對應標準庫函數remove

  

8.4 隨機訪問 lseek
輸入輸出通常是順序進行的每次調用read和write進行讀寫的位置緊跟在前一個操作的位置後但是,有時需要以任意的順序訪問檔案,系統調用lseek可以在檔案中任意移動位置而不實際讀寫任何資料long lseek(int fd,long offset,int orign);將檔案描述符fd的當前位置設定為offsetoffset是相對於origin指定的位置而言隨後進行的讀寫操作將從此位置開始使用lseek系統調用時,可以將檔案視為一個大數組,其代價是訪問速度慢一些標準庫函數fseek和系統調用lseek類似不同的是,前者的第一個參數是FILE *類型且發生錯誤時返回一個非0值

  

8.5 執行個體 --  fopen和getc函數的實現
標準庫中的檔案不是通過檔案描述符描述的,而是使用檔案指標描述的檔案指標是一個指向包含檔案各種資訊的結構的指標包含如下資訊:一個指向緩衝區的指標,通過它可以一次讀入檔案的一大塊內容一個記錄緩衝區中剩餘的字元數的計數器一個指向緩衝區下一個字元的指標檔案描述符描述讀寫入模式的標誌描述錯誤狀態的標誌描述檔案的資料結構包含在<stdio.h>中只供標準庫中其他函數使用的名字以底線開始,因此一般不會和使用者程式中的名字衝突

  

8.6 執行個體 -- 目錄列表
在UNIX中的目錄就是一種檔案ls只需讀取此檔案就可以獲得所有的檔案名稱但是如果需要擷取檔案的其他資訊,就需要系統調用

  

8.7 執行個體 -- 儲存分配程式
malloc在必要是調用系統以擷取更多的儲存空間malloc並不是從一個在編譯時間就確定的固定大小的數組中分配儲存空間而是在需要的時候想作業系統申請空間因為程式中的某些地方可能不通過malloc申請空間所以malloc管理的空間不一定是連續的這樣空閑儲存空間以空閑塊鏈表的方式組織每個塊包含一個長度 一個指向下一塊的指標及一個指向自身儲存空間的指標當有申請請求時,malloc將掃描空閑塊鏈表,直到找到一個足夠大的塊為止該演算法稱為 "首次適應"與之對應的演算法是"最佳適應"如果塊恰好與請求的大小符合將它從鏈表中移走並返回給使用者如果塊太大,則將它分成兩部分:大小合適的返回給使用者,剩下的部分留在空閑鏈表中如果找不到足夠大的塊,則想作業系統申請一個大塊並加入到空閑鏈表中釋放過程也是首先搜尋空閑鏈表以找到可以插入被釋放塊的合適位置如果與被釋放塊相鄰的任意一邊是空閑,則將兩塊合并成一個大塊由malloc返回的儲存空間滿足將要儲存的對象的對齊要求雖然機器類型各異,但是每個特定的機器都有一個最受限的類型如果最受限的類型可以儲存在某個特定的地址中則其他所以的類型也可以存放在此地址中向系統申請儲存空間是一個開銷很大的操作我們不希望每次malloc執行該操作UNIX系統調用sbrk(n)返回一個指標,該指標指向n個位元組的儲存空間如果沒有空閑空間,sbrk返回-1 

  

 

《C程式設計語言》筆記 (八) UNIX系統介面

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.