Linux 檔案IO 緩衝與非緩衝

2021-07-24 22:36:33 字數 3549 閱讀 6011

本地普通檔案io一般關注的是快取,一般都是同步阻塞的。普通檔案的file descriptor是block也是posix標準。這點不同於網路io,網路io要考慮傳輸兩邊程序處理等,設計之初就提供了帶狀態檢測的非同步操作方式,本地檔案io則必然要求高可靠性的。

不帶緩衝指的是每個readwrite都呼叫了核心的乙個系統呼叫。這些函式在呼叫的時候系統呼叫直接進行了磁碟檔案的寫入操作。

#include 

#include

int main()

打斷點可以看是直接呼叫的系統呼叫

(gdb) pt write

type = int ()

(gdb) bt

#0write () at ../sysdeps/unix/syscall-template.s:81

#10x00000000004005ad in main () at main.c:6

標準io提供快取的目的是盡可能減少使用read, write呼叫的數量。

標準io庫處理很多細節,如快取分配,以優化長度執行i/o,是在系統呼叫函式基礎上構造的,便於使用者使用。標準io函式fopen返回乙個指向file物件的指標。該物件管理該流所需要的所有資訊:用於實際io的檔案描述符,指向流快取的指標,快取的長度,當前在快取中的字元數,出錯標誌等。

標準輸入、標準輸出和標準出錯這三個標準io流通過預定義檔案指標stdin, stdout, stderr加以引用。這三個檔案指標同樣定義在標頭檔案中。

如:函式fputs將乙個以null符終止的字串寫到指定的流,終止符null不寫出。

#include 

int main()

打斷點看最終還是用的作業系統呼叫

(gdb) pt write

type

= int ()

(gdb) bt

#0 write () at ../sysdeps/unix/syscall-template

.s:81

#10x00007ffff7a8de53

in _io_new_file_write (f=

0x7ffff7dd4400

<_io_2_1_stdout_>, data

=0x7ffff7ff7000, n=

14) at fileops.c:1261

#20x00007ffff7a8f32c

in new_do_write (to_do=

14, data

=0x7ffff7ff7000

"hello, world!\n", fp=

0x7ffff7dd4400

<_io_2_1_stdout_>)

at fileops.c:538

#3 _io_new_do_write (fp=fp@entry=

0x7ffff7dd4400

<_io_2_1_stdout_>, data

=0x7ffff7ff7000

"hello, world!\n", to_do=

14) at fileops.c:511

#40x00007ffff7a8f703

in _io_new_file_overflow (f=

0x7ffff7dd4400

<_io_2_1_stdout_>, ch=

10) at fileops.c:876

#50x00007ffff7a9055c

in __gi__io_default_xsputn (f=f@entry=

0x7ffff7dd4400

<_io_2_1_stdout_>, data

=data@entry=

0x400624,

n=n@entry=

14) at genops.c:480

#60x00007ffff7a8e532

in _io_new_file_xsputn (f=

0x7ffff7dd4400

<_io_2_1_stdout_>, data

=, n=

14) at fileops.c:1353

#70x00007ffff7a83614

in __gi__io_fputs (str=

0x400624

"hello, world!\n", fp=

0x7ffff7dd4400

<_io_2_1_stdout_>) at iofputs.c:40

#80x0000000000400593

in main () at main.c:5

其中stdout是標準庫定義的乙個型別, 可以在標準庫源**看到, 也可以 gdb 看到起型別, 這個結構體中就有乙個欄位是檔案描述符,也是1,可以很容易檢視

(gdb) pt stdout

type = struct

_io_file *

(gdb) p stdout->_fileno

$1 = 1

/* standard streams.  */

extern

struct _io_file *stdin; /* standard input stream. */

extern

struct _io_file *stdout; /* standard output stream. */

extern

struct _io_file *stderr; /* standard error output stream. */

#define stdin stdin

#define stdout stdout

#define stderr stderr

全快取。在這種情況下,當填滿標準io快取後才進行實際io操作。對於駐在磁碟上的檔案通常是由標準io庫實施全快取的。

行快取。在這種情況下,當在輸入和輸出中遇到新行符時,標準io庫執行io操作。兩個限制:第乙個是:因為標準io庫用來收集每一行的快取的長度是固定的,所以只要填滿了快取,那麼即使還沒有寫乙個新行符,也進行io操作。第二個是:任何時候只要通過標準輸入輸出庫要求從(a)乙個不帶快取的流,或者(b)乙個行快取的流(它預先要求從核心得到資料)得到輸入資料,那麼就會造成重新整理所有行快取輸出流。

不帶快取。標準io庫不對字元進行快取。相當於用write系統呼叫, 如標準出錯流stderr通常是不帶快取的,這就使得出錯資訊可以盡快顯示出來。

ansi c要求下列快取特徵:

- 當且僅當標準輸入和標準輸出並不涉及互動作用裝置時,它們才是全快取的。

- 標準出錯決不會是全快取的。

參考:unix環境高階程式設計

linux不帶緩衝檔案IO

本博文設計的io不屬於ansi c的檔案io,所涉及的每乙個函式都是乙個系統呼叫。主要涉及posix.1的不帶快取的io操作的基礎部分。在linux核心中,對於乙個檔案的描述只需要乙個標示符即可。而不是乙個複雜的指標,僅僅是乙個int型的整數,有檔案描述符可以直接通過系統api直接操作核心資源,換句...

linux下的檔案緩衝IO

1 dup dup2 複製乙個現有的檔案描述符時,不會賦值檔案表。出現多個檔案描述符對應同一張檔案表的情況 dup 複製時系統會自動選擇乙個位置用的檔案描述符,通常選擇未使用的最小值 dup2 是程式設計師指定的新的檔案描述符,如果已被使用,則會強行關閉原始檔後繼續為我所有。dup.c 他們經常用來...

標準I O緩衝 全緩衝 行緩衝 無緩衝

說明 我只對網路資源進行了整合,方便學習 基於流的操作最終會呼叫read或者write函式進行i o操作。為了使程式的執行效率最高,流物件通常會提供緩衝區,以減少呼叫系統i o庫函式的次數。基於流的i o提供以下3種緩衝 全緩衝 直到緩衝區被填滿,才呼叫系統i o函式。對於讀操作來說,直到讀入的內容...