Unix中的不帶緩衝的檔案IO

2021-05-31 22:52:04 字數 3159 閱讀 9686

unix中的一切都是檔案:這是乙個相當經典的定義,在unix以及unix的衍生系統中這一概念都是成立的。說一切都是檔案,指的是在unix中任何東西都是用檔案來表示的。在unix中裝置是檔案,socket是檔案,fifo是檔案,管道..也是檔案。其實個人理解說unix中的一切都是檔案其實是說在unix中檔案是應用程式與系統(以及硬體設施)間溝通的「橋梁」。如/dev/hdc是乙個檔案,但它實際是乙個光碟(程式與光碟溝通的橋梁)。

概念性的東西:

檔案描述符:

對於核心,所有開啟的檔案都通過乙個檔案描述符來引用,檔案描述符是乙個非負整數(這也是為什麼socket返回的是乙個unsigned int 型別的原因,因為socket在unix中也是檔案,返回的實際是乙個檔案描述符,讀寫socket就是讀寫檔案)。乙個檔案可以對應著多個檔案描述符。

檔案共享

unix系統支援在不同程序間共享開啟的檔案。在介紹函式之前,先要說明這種共享。為此先介紹核心用於所有i/o的資料結構。

核心使用三種資料結構表示開啟的檔案,它們之間的關係決定了在檔案共享方面乙個程序對另乙個程序可能產生的影響。

(1) 每個程序在程序表中都有乙個記錄項,記錄項中包含有一張開啟檔案描述符表,可將其視為乙個向量,每個描述符占用一項。與每個檔案描述符相關聯的是:

(a) 檔案描述符標誌(close_on_exec)。

(b) 指向乙個檔案表項的指標。

(2) 核心為所有開啟檔案維持一張檔案表。每個檔案表項包含:

(a) 檔案狀態標誌(讀、寫、添寫、同步和非阻塞等)。

(b) 當前檔案偏移量。

(c) 指向該檔案v節點表項的指標。

檔案描述符,檔案表項,v節點的關係圖:

函式:1,open函式:呼叫open函式可以開啟或則建立乙個檔案。

#include

int open(const char* pathname,int oflag, ... /*mode_t mode*/);

pathname:檔名

oflag:檔案開啟的方式

mode:這個引數只有在建立檔案的時候才用到

oflag的說明:這個引數可以是下列乙個或多個常量進行「或」運算構成。

o_rdonly 唯讀

o_wronly 只寫

o_rdwr   讀,寫開啟

這三個引數是必須指定乙個而且只能指定乙個的,除此之外還可「或」上下列一些選項。

每次寫的時候都追加到檔案的尾部。(這個選項很有用,尤其是在多個程序中都同時開啟乙個檔案進行讀寫操作的時候,由於這兩個程序都有自己的檔案表項,但是卻都有共享同乙個v節點表項,而檔案的當前位置是記錄在v節點中的,所以就會導致寫亂的情況發生)

o_create

如果檔案不存在就新建乙個。這個時候mode引數就可以用來指定檔案的許可權了,如果不知定mode引數的話,當建立檔案的時候檔案的許可權就會由umask(檔案的掩碼)決定。

o_excl

如果指定了o_excl|o_create而且檔案存在的話open函式就會出錯(這可以檢測檔案是否已經建立)

o_trunc

如果檔案存在開啟時把檔案的長度截斷為0.

o_noctty

如果pathname指向的是乙個終端的情況下其作用。

o_nonbblock

如果pathname指的是乙個fifo,乙個特殊檔案塊或乙個字元特殊檔案,那麼開啟後對這個檔案的io操作就是非阻塞的。

2,create函式:

自從open函式可以指定三個引數,而且提供了o_create,o_trunc選項後這個函式就基本可以說廢掉了。它等價於:

open(pathname,o_create|o_trunc|o_rdwr,mode);

3,close函式:用於關閉乙個檔案描述符(釋放檔案描述符所指的檔案表項),同時會釋放加在這個檔案上的鎖(同步所用)。

#include

int close(int fd);

4,lseek函式:改變檔案描述符指定向的檔案位置(我覺得應該是記錄在檔案表項中的)

#include

off_t lseek(int fd,off_t offset,int whence);//如果成功返回新的偏移量,否則-1(如果檔案描述符引用的是乙個管道,fifo或者網路套接字就會出錯,應為他們是順序的,怎能亂seek)

fd:檔案描述符

offset:相對與whence指定的地方的偏移量。

whence:作為偏移的相對位置,seek_set檔案頭,seek_end檔案尾,seek_cur檔案的當前位置。

5,read函式:從開啟的檔案中讀資料。

#include

ssize_t read(int fd,void *buf,size_t nbyte);//返回讀到的字元數,如果到達檔案尾則返回0,出錯返回-1.

6,write函式:向開啟的檔案寫資料。

#include

ssize_t write(int fd,const void* buf,size_t nbyte);//成功返回寫入的位元組數,否則返回-1

7,dup,dup2函式:用於複製檔案描述符。返回的檔案描述符與原先的指向同乙個檔案表項。

int dup();

int dup2(int nfd);//nfd為用於希望的檔案描述符的值,如果nfd以開啟,就先關閉。

8,sync,fsync,fdatasync函式:由於unix採用了「延遲寫」的技術減少的磁碟讀寫次數,用於保證磁碟上實際檔案系統與緩衝區快取記憶體中內容的一致性。

#include

void sync(void);//把緩衝區中的內容寫如讀寫佇列,但不等待實際寫入磁碟。

int fsync(int fd);//對fd指定的檔案其作用,等待寫入磁碟操作,跟新檔案的屬性。

int fdatasync(int fd);//對fd指定的檔案其作用,等待寫入磁碟,不更新檔案的屬性。

9,fcntl函式:改變開啟的檔案的性質,這個函式的東西挺多的,但是記住子要想該變開啟檔案的性質就用這個函式就行。

#include

int fcntl(int fd,int cmd,.../*int arg*/);

10,ioctl函式,這個函式很雜,不能用其他的io函式解決的就用這個函式,這個函式使用最多的是終端i/o操作方面的。

#include

#include

#include

int ioctl(int fd,int request,...);

不帶緩衝的I O

unix系統中的大多數檔案i o只需要用到5個函式 open read write lseek以及close。這些函式經常被稱為不帶緩衝的i o。術語 不帶緩衝 指的是每個read和write都呼叫核心中的乙個系統呼叫。檔案描述符 對於核心而言,所有開啟的檔案都通過檔案描述符引用。檔案描述符是乙個非...

linux不帶緩衝檔案IO

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

檔案I O(不帶緩衝)概述

unix系統中大多數檔案i o只需用到5個函式 open read write lseek以及close。這些函式經常被稱為不帶緩衝的i o unbuffered i o 術語不帶緩衝指的是每個read和write都呼叫核心中的乙個系統呼叫。這些不帶緩衝的i o函式不是iso c的組成部分,但是,它...