linux的文件系統
linux 文件I/O教程(1)
一,文件描述符
對內核而言,所以打開的文件都通過文件描述符引用。每個進程都有一些與之關聯的文件描述符。文件描述符是一個非負整數。當打開一個現有文件或創建一個新文件時,內核向進程返回一個文件描述符。當讀或寫一個文件時,使用open或creat返回的文件描述符標識該文件,將其作爲參數傳送給read和write。
一般有三個以及打開的文件描述符,他們是:
0:標準輸入 STDIN_FILENO
1:標準輸出 STDOUT_FILENO
2標準錯誤輸出 STDERR_FILENO
每行後面的符號常量是依從POSIX而定的。
open函數
#include
#include
#include
int open(const char *pathname, int flags);
int open(const char *pathname, int flags,mode_t mode);
pathname是要打開或創建文件的名字。
flag用來定義打開文件所採取的的動作,必須調用以下模式之一
O_RDONLY, O_WRONLY, O_RDWR分別代表只讀,只寫,讀寫方式打開。
open還可以包括以下可選模式的組合
O_APPEND:把寫入數據追加到文件的尾端
O_CREAT:若文件不存在,則創建它。使用此選項時,需要第三個參數mode,用其指定該新文件的訪問權限。
O_EXCL:如果同時指定了O_CREAT,而文件存在,則會出錯。用此可以測試一個文件是否存在,如果存在,則創建文件,這使測試和創建兩者成爲一個原子操作。
O_TRUNC: 如果此文件存在,而且爲只寫或讀寫成功打開,則將其長度截爲0。
open返回的文件描述符一定是最小的未用描述符數值。這一點被某些應用程序用在標準輸入,標準輸出或標準錯誤輸出上。如,一個程序關閉了自己的標準輸出,然後再次調用open,文件描述符1就會被調用,並且標準輸出將被有效的重定向到另一個文件或設備。
POSIX規範還標準化了一個creat調用,此函數等效於
open(pathname,O_WONLY |O_CREAT | O_TRUNC, mode);
close函數
#include
int close(int fd);
close調用終止一個文件描述符fd與對應文件之間的關聯。文件描述符被釋放後並能重新使用。close調用成功返回0,出錯返回-1.
關閉一個文件時會釋放該進程加在文件上的所有記錄鎖。當一個進程終止時,內核自動關閉它所有打開的文件。
lseek函數
每個打開的文件都有一個與其相關聯的”當前文件偏移量”。按系統默認情況,當打開一個文件時,除非指定O_APPEND選項,否則該偏移量被設置爲0。lseek可以爲一個打開的文件設置偏移量。
#include
#include
off_t lseek(int fd, off_t offset, intwhence);
offset用來指定位置,whence參數定義該偏移值的用法。whence可取以下值:
SEEK_SET: The offset is set to offset bytes.
SEEK_CUR: The offset is set to its current locationplus offset bytes.
SEEK_END: The offset is set to the size of the fileplus offset bytes.
成功調用返回從文件頭到文件指針被設置處的字節偏移值,失敗返回-1。參數offset定義在中。
當偏移量大於文件長度時,出現空洞,空洞不佔用存儲區。
read函數
#include
ssize_t read(int fd, void *buf, size_tcount);
將與文件描述符fd關聯的文件中讀入count個字符放到buf中。返回讀入的字節數,它可能小於請求的字節數。如果read調用返回0,就表示未讀入任何數據,已到達了文件尾。返回-1,就表示出錯。
write函數
#include
ssize_t write(int fd, const void *buf,size_t count);
把緩衝區buf的前count個字節寫入與文件描述符fd相關聯的文件中。返回實際寫入的字節數,通常與count值相同;否則表示出錯。出錯的一個常見原因是:磁盤已寫滿,或者超出了一個給定進程的文件長度限制。
實例:創建一個文件,寫入數據,移動當前偏移量,在讀數據。
#include//必須最早出現,因爲它可能會影響到其他頭文件。#include
#include
#include
#include
int main()
char* filename = ".//file";
char buf[100];
char buf1[5];
int fd;
printf("open a file to writen");
if((fd = open(filename,O_RDWR|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH ))==-1)
perror("cannot open filen");
return 1;
printf("open file successfully!n");
printf("input a string:");
gets(buf);
//write intofile
if(write(fd,buf,strlen(buf)) !=strlen(buf))
perror("cannot write intofilen");
return 1;
close(fd);
printf("open file to read.n");
if((fd=open(filename,O_RDONLY)) == -1)
perror("cannot open thefile.n");
return 1;
if(lseek(fd,3,SEEK_SET) == -1)
perror("lseek erroen");
return 1;
//read from the file
if(read(fd,buf1,4)==-1)
perror("read error.n");
return 1;
printf("read from file is%sn",buf1);
close(fd);
return 0;
執行與輸出結果:
root@:~$gcc -o io io.c
root@:~$./io
open a file towrite
open filesuccessfully!
input a string:akxivbaslzkncxcasbxbwwvaidxbd
open file toread.
read from fileis ivba
linux 文件I/O教程(2)下面介紹了linux中有關文件I/O的相關內容,內核使用三種數據結構表示打開的文件,他們之間的關係決定了在文件共享方面一個進程對另一個進程可能產生的影響。
一,文件共享
內核使用三種數據結構表示打開的文件,他們之間的關係決定了在文件共享方面一個進程對另一個進程可能產生的影響。
1) 每個進程在進程表中都有一個記錄項,記錄項中包含一張打開文件描述表,可將其視爲一個矢量,每個描述符佔用一項。與每個文件描述符相關聯的是:
a) 文件描述符標誌
b) 指向一個文件表項的指針
2) 內核爲所有打開文件維持一張文件表。每個文件表項包含:
a) 文件狀態標誌(讀、寫、讀寫、添些、同步和阻塞等)
b) 當前文件偏移量
c) 指向文件v節點表項的指針
3) 每個打開文件(或設備)都有一個v節點(v-node)結構。v節點包含了文件類型和對比文件進行各種操作的函數的指針。對於大多數文件,v節點還包含了該文件的i節點。i節點包含文件所有者、文件長度、文件所在的設備、指向文件實際數據塊在磁盤上所在位置的指針等。
打開文件的`內核數據結構
如果兩個進程各自打開了同一個文件,則如圖2所示。假定第一個進程在文件描述符3打開上該文件,而另一個進程在文件描述符4上打開該文件。每個進程都得得到一個文件表項,但對一個給定的文件只有一個v節點表項。每個進程都有自己的文件表項的一個理由是:使每個進程都有自己對該問價的當前偏移量。
現在對前一節文件I/O(1)的幾個操作進一步說明:
1. 完成write之後,文件中當前偏移量即所增加的字節數。如果當前偏移量大於文件長度,則將i節點中當前文件長度設爲當前文件偏移量。
2. 用O_APPEND打開一個文件,相應標誌會被設置到文件狀態標識中。每次寫時,當前偏移量會被設置爲i節點中的文件長度
3. lseek定位到文件尾端時,則文件當前偏移量會被設置爲當前文件長度。
可能有多個文件描述符指向同一文件表項。調用dup和fork時都能看到這一點。
多個進程讀同一文件能正確工作。但多個進程寫同一文件時,可能產生預期不到的後果。可以利用原子操縱避免這種情況。
原子操作
一般而言,原子操作指的是由多部組成的操作。如果該院自地執行,要麼執行完所以步驟,要麼一步也不執行。
1. 添加至一個文件
考慮一個進程,它要講數據添加到一個文件尾端。早期UNIX不支持open,所以可以如下實現:
if(lseek(fd, 0L, 2)<0)
err_sys(“lseekerror”);
if(write(fd, buf, 100) != 100)
err_sys(“writeerror”);
對於單個進程,這段程序能正常工作。但多個進程就不一定。結社進程A和B都對同一文件進行添加操作。每個進程都打開該文件,此時數據結構之間關係如圖2中所示。假定A調用lseek,將A的當前偏移量設置爲1500。進程B執行lseek也將其當前偏移量設爲1500。然後B調用write,將當前偏移量增至1600。然後內核又進行進程切換使進程A恢復運行,當A調用write時,從其當前偏移量1500處將數據寫入,將替換B剛寫入到該文件中的數據。
問題出在邏輯操作“定位到文件尾端處,然後寫“使用了兩個分開的函數調用。解決辦法是使這兩個操作成爲一個原子操作。O_APPEND標識,使內核每次對文件進行寫之前,都將進程當前偏移量設置到該文件的尾端處。
2.pread和pwrite函數
原子性地定位搜索和執行I/0。
#include
ssize_t pread(int fd, void *buf, size_tcount, off_t offset);
ssize_t pwrite(int fd, const void *buf,size_t count, off_t offset);
ssize_t pread(int fd, void *buf, size_tcount, off_t offset);
ssize_t pwrite(int fd, const void *buf,size_t count, off_t offset);
dup和dup2函數
#include
int dup(int oldfd);
int dup2(int oldfd, int newfd);
上面兩個函數都可用來複制一個現存的文件描述符。
由dup返回的新文件描述符一定是當前可用文件描述符中的最小數值。用dup2則可以用newfd參數指定新描述符的數值。如果newfd已經打開,則先將其關閉。如果newfd等於oldfd,則dup2返回newfd而不關閉它。
圖3.3顯示了這種情況。
假定我們的進程執行了:
newfd = dup(1);
當此函數執行時,假設下一個可用的描述符是3。因爲這兩個描述符指向同一個文件表項,所以他們共享文件標誌以及同一文件偏移量。
sync、fsync和fdatasync
#include
void sync(void);
int fsync(int fd);
int fdatasync(int fd);
當將數據寫入文件時,內核通常將數據複製到一個緩衝區,直到緩衝區寫滿,再將緩衝區排路輸出隊列,然後等待其到達隊首,才進行實際的I/O操作。這種輸出防暑被稱爲延遲寫。延遲寫減少了磁盤的讀寫次數,但卻降低了文件內容的跟新速度。當系統發生故障時,延遲寫可能造成文件跟新內容的丟失。爲了保證磁盤上實際文件系統與緩衝區高速緩存中內容一致性,UNIX系統提供了sync、fsync和fdatasync 三個函數。
fcntl函數
#include
#include
int fcntl(int fd, int cmd, ... /* arg */ );
可以改變已經打開文件的性質。
複製一個現有的描述符(cmd=F_DUPFD)
獲得或設置文件描述符(cmd=F_GETFD|F_SETFD)
獲得或設置文件狀態標誌(cmd=F_GETFL|F_SETFL)
獲得或設置異步I/O所有權(cmd=F_GETOWN|F_SETOWN)
獲得或設置記錄鎖(cmd=F_GETLK|F_SETLK、F_SETLKW)
可以用fcntl函數設置文件狀態,常用設置套接字描述符爲非阻塞O_NONBLOCK
ioctl函數
#include
int ioctl(int d, int request, ...);
提供了一個用於控制設備及其描述符行爲和配置底層服務的接口。
/dev/fd
打開文件/dev/fd/n等效於複製描述符n。
相關文章
-
Linux認證系統管理:linuxmail命令發送郵件失敗
總結是在某一特定時間段對學習和工作生活或其完成情況,包括取得的成績、存在的問題及得到的經驗和教訓加以回顧和分析的書面材料,它可以提升我們發現問題的能力,讓我們抽出時間寫寫總結吧。總結你想好怎麼寫了嗎?以下是小 -
Linux關閉selinux安全子系統的技巧
審計人員個人工作總結 篇1我於20xx年2月調至縣教體局從事教育內審工作,在此工作期間,工作態度嚴謹認真,緊緊圍繞各項工作目標,堅持“依法審計、服務大局、圍繞中心、突出重點、求真務實”的審計工作方針,履行好崗位職責,在 -
Linux認證系統管理:linux下搭建ftp
最近爲了方便目標板與PC機上LINUX之間的通訊,就在LINUX搭建了FTP,工作不難,寫個總結。主要經過以下幾個步驟: 1.檢查是否安裝了vsftpd服務器可以用rpm -q vsftpd命令來查看,若顯示"vsftpd-1.1.3-8",則說明系統已經安裝vs -
Linux認證基礎知識:linux操作系統目錄結構
linux 目錄結構/: 根目錄,一般根目錄下只存放目錄,不要存放文件,/etc、/bin、/dev、/lib、/sbin應該和根目錄放置在一個分區中/bin:/usr/bin: 可執行二進制文件的目錄,如常用的命令ls、tar、mv、cat等。/boot: 放置li -
紅旗Linux系統配置LILO文件的方法
LILO文件可以幫助Linux中多個操作系統的並存,通過LILO文件,我們可以選擇要進入的系統。因此在安裝了多個操作系統的Linux中,LILO文件的配置是非常重要的。我們應該如何進行LILO文件的.配置呢?現在小編就告訴大家LILO文件 -
實用的Linux/Unix系統磁帶管理命令
混合性皮膚多見於25-35歲之間的人。中國大部分人都屬於此類皮膚。現代人混合性皮膚的人越來越多了,除了一些人是天生的混合性皮膚,還有一部分人是隨着壓力而變成混合性皮膚。要想護理好混合性皮膚,必須採用正 -
Linux操作系統文件系統基礎知識
Linux操作系統誕生於1991 年10 月5 日(這是第一次正式向外公佈時間)。下面是小編收集的Linux操作系統文件系統基礎知識,希望大家認真閱讀! 一 、Linux文件結構文件結構是文件存放在磁盤等存貯設備上的組織方法。主 -
Linux系統文件系統優化及磁盤檢查的方法
Linux中數據塊是儲存數據的基本數據單元,在linux中可以設置3中數據塊大小分別是1024(1kB),2048(2KB),4096(4KB)。數據塊大小決定了文件磁盤佔有量,打個比方如果你設置了數據塊大小是1024,不管你的文件有多大,至少要佔1KB -
Linux系統管理:linux修改鍵盤按鍵
respected company leaders:hello!i was about to nanning vocational and technical college graduate students in an accounting profession. from the "nanning information port" the newspapers and magazines, -
怎麼使用ln命令在Linux系統中創建連接文件
在Linux中ln命令用來爲文件創建連接,連接類型分爲硬連接(Hard Link)和符號連接(Symbolic Link)兩種,默認的連接類型是硬連接。如果要創建符號連接必須使用"-s"選項。那麼怎麼使用ln命令在Linux系統中創建連接文件?下面