系統呼叫是在核心空間執行的,那麼我們就需要了解在核心中是如何標識檔案的。對於核心而言,所有開啟的檔案都通過檔案描述符(簡稱fd)引用就是標識
檔案描述符是乙個非負整數,指代被開啟的檔案,當開啟乙個現有的檔案或建立乙個新檔案時,核心向程序返回乙個檔案描述符,將其作為引數給系統呼叫的i/o操作。
posix標準要求每次開啟檔案時,必須從小到大申請檔案描述符,那麼最小的檔案描述符是幾呢?不是0,因為系統已經規定了前三個:
檔案描述符
posix名稱 (常量定義在標頭檔案)
用途stdio流
0stdin_fileno
標準輸入
stdin
1stdout_fileno
標準輸入
stdout
2stderr_fileno
標準錯誤
stderr
所以 最小的檔案描述符從3開始,即開啟第乙個檔案open()返回的檔案描述就是3。
我們可以通過指令sysctl -a | grep fs.file-max
來檢視最多可以開啟多少個檔案:
同時,核心為了防止乙個程序建立多個檔案,占用檔案描述符,對單個程序建立檔案的上限也做了規定,可以用ulimit -n
檢視
1、帶緩衝區的i/o
含義
:
就是在記憶體開闢緩衝區,當執行讀檔案操作時,先把磁碟檔案讀到緩衝區,進行一次讀取,再根據程式需要將資料給讀給變數。
【舉個栗子】庫檔案i/o函式就是帶緩衝區的,如fopen,fread等
優點:
和外存的互動次數由緩衝區大小決定,如果緩衝區大,和對外存操作少。如果進入核心讀取資料,那麼互動次數會少,因為它會盡可能地一次讀取資料。故執行速度就快,效率高。
2、不帶緩衝區的i/o
含義
就是執行i/o函式時,根據程式需求,直接將資料給變數。不帶緩衝區i/o依賴於作業系統,即系統級輸入輸出
【舉個栗子】
系統呼叫i/o,如open等
缺點
會和核心進行多次互動,所以執行速度會慢
。
【注意】
我們不能以偏概全,不帶緩衝區地read系統呼叫函式一定比帶緩衝區地fread庫函式速度慢,這是不對的,只有合適,沒有不好。
【舉個栗子】
read需要進行多次核心態和使用者態的互動,而fread則互動少,如果我們是順序讀取資料,那麼fread即帶緩衝區的更快,但是如果我們隨機讀取資料,這時緩衝區的作用降低,read反而速度快。所以要在一定的情景下來找最合適的。
介紹關於man的指令,方便檢視函式的資訊
指令含義
man 1 command
檢視命令的幫助手冊
man 2 系統呼叫
檢視系統呼叫手冊
man 3 庫函式
檢視庫函式的使用手冊
open()函式開啟或建立乙個檔案,函式原型為:
# include。
int open(const char* pathname,int flags,…/*mode_t*/)
引數說明:第三個引數的形式我們稱為可變引數。
pathname
:表示開啟或建立檔案的路徑和名字。
flags
:表示開啟檔案的方式或建立,可以選擇的引數為: 引數
含義選擇
o_rdonly
唯讀開啟
必須指定,但不能和2,3兩個引數任何乙個同時存在
o_wronly
只寫開啟
必須指定,但不能和1,3兩個引數任何乙個同時存在
o_rdwr
讀寫開啟
必須指定,但不能和1,2兩個引數任何乙個同時存在
o_creat
若檔案不存在則建立它,此時第三個引數有效
可以選擇,不要求必須有
追加到檔案末尾
可以選擇,不要求必須有
o_excl
測試檔案是否存在
如果同時指定了o_creat,而檔案存在,則會出錯,不存在建立,使得測試和建立稱為原子操作
o_trunc
如果此檔案存在,而且為唯讀或讀寫開啟,則將其長度截斷為0,即每次開啟檔案清除以前的內容
可選擇o_nonblock
如果檔案是乙個管道,特殊檔案,套接字等,則此選項為檔案的本次開啟操作和後續的i/o操作設定為非阻塞。常和et模式結合,將檔案描述符設為非阻塞
可選擇可變引數
:只有當引數flags種包含o_creat建立檔案的常量時,這個引數才存在,它要指定檔案的許可權,格式為【0***】,0是乙個識別符號,讀r許可權為4,寫w許可權為2,執行x許可權為1。
返回值
:成功返回當前未使用的檔案描述符,失敗返回-1。
read()函式從開啟檔案中讀取資料,函式原型為:
# includessize_t read(int files,void*buf,size_t nbytes);
引數含義:
files
:檔案描述符。
buf
:儲存讀取到的資料的變數
nbytes
:一次讀多少位元組。
成功返回讀到的位元組,到達檔案結尾返回0,出錯返回-1.
讀到那裡,檔案偏移量就到那裡,所以以前讀過的要想再讀,需要移動檔案偏移量。
write()函式向開啟的檔案寫資料,函式原型為:
# includessize_t write(int files,const *buf,size_t nbytes);
引數含義:
files表示檔案描述符。成功返回-,失敗返回-1。
當乙個程序終止時,核心自動關閉它所有開啟的檔案,這個是close的隱式使用,不是顯式。
lseek()為乙個開啟的檔案設定其偏移值,函式原型為:
# includeoff_t lseek (int files,off_t offset,int whence)
引數說明;
files表示檔案描述符。
offset:表示偏移的位元組,可正可負和whence引數有關。
whence:表示從**開始偏移,可以取值為: 引數
含義seek_set
將該檔案的偏移量設定為距離檔案開始處offset位元組
seek_cur
將該檔案的偏移量設定為距離當前位置處offset位元組
seek_end
將該檔案的偏移量設定為距離末尾處offset位元組
返回值
:成功返回新的檔案偏移量,出錯返回-1。
系統呼叫是陷入中斷,進入核心的過程,是通向作業系統本身的介面,當系統呼叫i/o函式發生時,核心將呼叫核心相關函式來實現,如(sys_read(),sys_write()等),系統呼叫時乙個從使用者態->核心態->使用者態的過程,下面我們來看一下它的過程時怎樣的:
那我們簡略的畫出這個過程,這個只是為了方便理解畫出的圖,函式和對應的呼叫號並不是核心中真正的資料。
linux 系統呼叫
使用者應用可以通過兩種方式使用系統呼叫。第一種方式是通過c庫函式,包括系統呼叫在c庫中的封裝函式和其他普通函式。圖5.2 使用系統呼叫的兩種方式 第二種方式是使用 syscall巨集。2.6.18版本之前的核心,在include asm i386 unistd.h檔案中定義有7個 syscall巨集...
Linux系統呼叫
一 實驗目的和要求 1.學習linux核心的配置和編譯 2.深入理解linux系統呼叫 3.理解arm和x86的cpu模式 系統模式 使用者模式 的不同 4.掌握核心模組的編寫方法。二 實驗器材 1.linux實驗板卡一塊 2.5v 1a電源乙個 3.microusb線一根 4.macos一台 5....
Linux系統呼叫
linux系統呼叫 系統呼叫 system call 是使用者空間訪問核心的唯一手段,除異常和陷入外,他們是核心唯一的合法入口。通常情況下應用程式是通過應用程式設計介面api來訪問函式,而不是直接使用系統呼叫來程式設計。作業系統通常是通過中斷從使用者態切換到核心態。中斷就是乙個硬體或軟體請求,要求c...