西西軟件園多重安全檢測下載網(wǎng)站、值得信賴的軟件下載站!
軟件
軟件
文章
搜索

首頁西西教程操作系統(tǒng) → Linux系統(tǒng)中的函數(shù)文件操作教程

Linux系統(tǒng)中的函數(shù)文件操作教程

相關軟件相關文章發(fā)表評論 來源:geek_ling時間:2012/8/4 10:51:28字體大。A-A+

作者:geek_ling點擊:86次評論:2次標簽: Linux

  • 類型:電子資料大小:768KB語言:中文 評分:10.0
  • 標簽:
立即下載

文件是linux中的一個重要概念。在Linux中,一切(幾乎一切)都是文件。簡單的說,C中基本的的printf()函數(shù),scanf()函數(shù),其實都屬于文件操作。

對于文件操作,雖然都是通過函數(shù)調(diào)用的方式實現(xiàn),卻還是能分為兩類:系統(tǒng)調(diào)用和庫函數(shù)。

這篇文章將先介紹linux中文件的概念,系統(tǒng)調(diào)用和庫函數(shù)的概念 ,然后具體的討論兩種方式下的文件操作。

博文的主要內(nèi)容如下:

Linux 中的文件

文件訪問-庫函數(shù)

文件訪問-系統(tǒng)調(diào)用

庫函數(shù)

標準 I/O 庫

/proc文件系統(tǒng)

1 Linux中的文件

1.1概念

按照普通的定義,文件不過是一堆數(shù)據(jù),在往下說,就是存儲器中的0101。。。而我們這里討論的文件有了更廣的定義。對于Linux中的文件,我的理解是:

Linux中的文件具有的特點是:可通過操作系統(tǒng)或者程序?qū)ν馓峁┬畔,也能對?nèi)輸入信息,可以被創(chuàng)建,刪除。

Linux中,文件有特別重要的意義,他們?yōu)椴僮飨到y(tǒng)和設備提供了一個簡單而統(tǒng)一的接口。在Linux中,幾乎一切都可以看做是文件 。

這就意味著,普通程序完全可以像使用文件(普通定義)那樣使用磁盤文件、串行口、打印機和其他設備。

硬件設備在linux操作系統(tǒng)中也被表示為文件。例如,可以通過如下命令把cd-rom驅(qū)動器掛載為一個文件,

#mount -t iso9660 /dev/hdc /mnt/cdrom

#cd /mnt/rom

然后,就能像訪問普通文件那樣在cd-rom目錄中漫游。

1.2操作

和操作一般意義上的文件一樣,linux中對文件的操作只需要五個基本的函數(shù):

open、close、read、write和ioctl

通過調(diào)用這幾個函數(shù)就能對linux中的文件進行讀、寫等操作。不過,這種操作又分為系統(tǒng)調(diào)用和庫函數(shù)調(diào)用。簡單的說,系統(tǒng)調(diào)用是最直接的方式,

庫函數(shù)調(diào)用最終也是通過系統(tǒng)調(diào)用實現(xiàn)的。可認為庫函數(shù)調(diào)用是對系統(tǒng)調(diào)出于效率考慮而做出的優(yōu)化。

庫函數(shù)調(diào)用和系統(tǒng)調(diào)用的區(qū)別和聯(lián)系請參看:linux系統(tǒng)調(diào)用和庫函數(shù)調(diào)用的區(qū)別

我們用很少的函數(shù)就可以對文件和設備進行訪問和控制。這些函數(shù)就是所謂的系統(tǒng)調(diào)用,由操作系統(tǒng)直接提供,他們是通向操作系統(tǒng)本身的接口。

操作系統(tǒng)的核心部分,既內(nèi)核,其實就是一組設備驅(qū)動程序。這是一些對硬件進行控制的接口。

2 文件訪問-系統(tǒng)調(diào)用

通過系統(tǒng)調(diào)用來訪問文件是最直接的方式。系統(tǒng)調(diào)用函數(shù)直接作用于操作系統(tǒng)內(nèi)核的設備驅(qū)動程序從而實現(xiàn)文件訪問。

2.1 文件描述符

在系統(tǒng)中需要處理的文件(讀、寫操作)需要一個標識,以便在其它地方能識別出這個文件,于是就產(chǎn)生了文件描述符。文件描述符是一些小值整數(shù),簡單的說就是

一個文件ID用于在系統(tǒng)中唯一的標識文件。文件描述符的總數(shù)也就是系統(tǒng)可以打開文件的最多個數(shù),這取決于系統(tǒng)的配置情況。

當開始運行程序時,也就是系統(tǒng)開始運行時,它一般會有三個已經(jīng)打開的文件描述符。他們是:

0:標準輸入

1:標準輸出

2:標準錯誤

其它文件的文件描述符,在調(diào)用文件打開函數(shù)open時返回。這就是說,每個設備對應著一個文件描述符。文件描述符由操作系統(tǒng)分配,每次分配最小的。

2.2 write系統(tǒng)調(diào)用

write,就是把緩沖區(qū)的數(shù)據(jù)寫入文件中。注意,這里的文件時廣泛意義的文件,比如寫入磁盤、寫入打印機等等。

Linux 中write()的函數(shù)原型:

size_t write(int fildes, const void *buf, size_t nbytes);

參數(shù)說明:

fildes:文件描述符,標識了要寫入的目標文件。例如:fildes的值為1,就像標準輸出寫數(shù)據(jù),也就是在顯示屏上顯示數(shù)據(jù);如果為 2 ,則想標注錯誤寫數(shù)據(jù)。

*buf:待寫入的文件,是一個字符串指針。

nbytes:要寫入的字符數(shù)。

函數(shù)返回值:size_t  返回成功寫入文件的字符數(shù)。需要指出的是,write可能會報告說他寫入的字節(jié)比你所要求的少。這并不一定是個錯誤。在程序中,你需要檢查

error已發(fā)現(xiàn)錯誤,然后再次調(diào)用write寫入剩余的數(shù)據(jù)。

請看下面的例子:

運行結果:

這個程序只在標準輸出上顯示一條消息。

read系統(tǒng)調(diào)用

系統(tǒng)調(diào)用read是從文件中讀出數(shù)據(jù)。要讀取的文件用文件描述符標識,數(shù)據(jù)讀入一個事先定義好的緩沖區(qū)。他返回實際讀入的字節(jié)數(shù)。

Linux中read的函數(shù)原型:

size_t read(int fildes, void *buf, size_t nbytes);

參數(shù)說明:

fildes:文件描述符,標識要讀取的文件。如果為0,則從標準輸入讀數(shù)據(jù)。類似于scanf()的功能。

*buf:緩沖區(qū),用來存儲讀入的數(shù)據(jù)。

nbytes:要讀取的字符數(shù)。

返回值:size_t返回成功讀取的字符數(shù),它可能會小于請求的字節(jié)數(shù)。

運行結果:

open系統(tǒng)調(diào)用

系統(tǒng)調(diào)用open的作用是打開一個文件,并返回這個文件的描述符。

簡單地說,open建立了一條到文件或設備的訪問路徑。如果操作成功,它將返回一個文件描述符,read和write等系統(tǒng)調(diào)用使用該文件描述符對文件或

設備進行操作。這個文件描述符是唯一的,他不會和任何其他運行中的進程共享。如果兩個程序同時打開一個文件,會得到兩個不同的問價描述符。如果

同時對兩個文件進行操作,他們各自操作,互補影響,彼此相互覆蓋(后寫入的覆蓋先寫入的)為了防止文件按讀寫沖突,可以使用文件鎖的功能。這不是

本次重點,以后介紹。

Linux中open的函數(shù)原型有兩個:

int open(const char *path, int oflags);

int open(const char *path, int oflags, mode_t mode );

參數(shù)說明。

path:準備打開的文件或設備名字。

oflags:指出要打開文件的訪問模式。open調(diào)用必須指定如下所示的文件訪問模式之一:

open調(diào)用哈可以在oflags參數(shù)中包括下列可選模式的組合(用”按位或“操作):

O_APPEDN: 把寫入數(shù)據(jù)追加在文件的末尾。

O_TRUNC: 把文件長度設為零,丟棄以后的內(nèi)容。

O_CREAT: 如果需要,就按參數(shù)mode中給出的訪問模式創(chuàng)建文件。

O_EXCL: 與O_CREAT一起調(diào)用,確保調(diào)用者創(chuàng)建出文件。使用這個模式可防止兩個程序同時創(chuàng)建一個文件,如果文件已經(jīng)存在,open調(diào)用將失敗。

 關于其他可能出現(xiàn)的oflags值,請看考open的調(diào)用手冊。

mode:

當使用哦、O_CREAT標志的open來創(chuàng)建文件時,我們必須使用三個參數(shù)格式的open調(diào)用。第三個參數(shù)mode 是幾個標志按位OR后得到的。他們是:

S_IRUSR: 讀權限,文件屬主。

S_IWUSR:寫權限,文件屬主。

S_ IXUSR:執(zhí)行權限,文件屬主。

S_IRGRP:讀權限,文件所屬組。

S_IWGRP:寫權限,文件所屬組。

。。。。

請看下面例子:

open("myfile", O_CREAT, S_IRUSR|S_IXOTH ;

他的作用是創(chuàng)建一個名為myfile 的文件,文件屬主擁有讀權限,其他用戶擁有執(zhí)行權限,且只有這些權限。

運行結果:

程序創(chuàng)建了一個名為myfile的文件,文件屬主有讀權限,其他用戶有執(zhí)行權限,且只有這些權限。

close系統(tǒng)調(diào)用

close系統(tǒng)調(diào)用用于“關閉”一個文件,close調(diào)用終止一個文件描述符fildes以其文件之間的關聯(lián)。文件描述符被釋放,并能夠重新使用。

close成功返回1,出錯返回-1.

#Include<unistd.h>

int close(int fildes);

ioctl系統(tǒng)調(diào)用

ioctl提供了一個用于控制設備及其描述符行為和配置底層服務的接口。終端、文件描述符、甚至磁帶機都可以又為他們定義的ioctl,具體

細節(jié)可以參考特定設備的使用手冊。

下面是ioctl 的函數(shù)原型

#include<unistd.h>

int ioctl(int fildes, int cmd,,,,,,);

ioctl對描述符fildes指定的對象執(zhí)行cmd 參數(shù)中所給出的操作。

 其他和文件管理有關的系統(tǒng)調(diào)用

還有許多其他的系統(tǒng)調(diào)用能對文件進行操作。

幾個常用的如:lseek()對文件描述符fildes指定文件的讀寫指針進行設置,也就是說,它可以設置文件的下一個讀寫位置。

fstat,stat,lstat 是和文件描述符相關的函數(shù)操作,這里就不做介紹。

dup,dup2系統(tǒng)調(diào)用。dup提供了復制文件描述符的方法,使我們能夠通過兩個或者更多個不同的文件描述符來訪問同一個文件。這可以用于

在文件的不同位置對數(shù)據(jù)進行讀寫。

4 庫函數(shù)

在輸入、輸出操作中,直接使用系統(tǒng)調(diào)用效率會非常底。具體原因有二:

系統(tǒng)調(diào)用會影響系統(tǒng)性能。與函數(shù)調(diào)用相比,系統(tǒng)調(diào)用的開銷大。因為在執(zhí)行系統(tǒng)調(diào)用的時候,要切換到內(nèi)核代碼區(qū)執(zhí)行,然后再返回用戶代碼。這必然就需要大量的時間開支。一種解決辦法是:盡量減少系統(tǒng)調(diào)用的次數(shù),讓每次系統(tǒng)調(diào)用完成盡可能多的 任務。例如每次系統(tǒng)調(diào)用寫入大量的字符而不是單個字符。

硬件會對系統(tǒng)調(diào)用一次能讀寫的數(shù)據(jù)塊做一定的限制。例如,磁帶機通常的寫操作數(shù)據(jù)塊長度是10k,如果縮寫數(shù)據(jù)不是10k的整數(shù)倍,磁帶機還是會以10k為單位繞磁帶,這就在磁帶上留下空隙。

為了提高文件訪問操作的效率,并且使得文件操作變得更方便,Linux發(fā)行版提供了一系列的標準函數(shù)庫。他們是一些由函數(shù)構成的集合,你可以在自己的程序方便的中使用它們,

去操作文件。提供輸出緩沖功能的標準I/O庫就是這樣的例子。你可以高效的寫任意長度的數(shù)據(jù)塊,庫函數(shù)則在需要的時候安排底層函數(shù)調(diào)用(系統(tǒng)調(diào)用)

也就是說,庫函數(shù)在用戶和系統(tǒng)之間,增加了一個中間層。如下圖所示:

庫函數(shù)是根據(jù)實際需要而包裝好的系統(tǒng)調(diào)用,用戶可在程序中方便的使用庫函數(shù),如標準I O庫(稍后會講)

5 標準I/O庫

 標準I/O庫及其頭文件<stdio.h>為底層I/O系統(tǒng)調(diào)用提供了一個通用的接口。這個庫現(xiàn)在已經(jīng)成為ANSI標準C的一部分,而前面所講的系統(tǒng)調(diào)用卻不是。

標準I/O庫提供了許多復雜功能的函數(shù),用于格式化輸出和掃描輸入,它還負責滿足設備的緩沖需求。

在許多方面,使用標準I/O庫和使用底層文件描述符類似。需要先打開一個文件,已建立一個文件訪問路徑(也就是系統(tǒng)調(diào)用中的文件描述符)

在標準I/O庫中,與文件描述符對應的叫 流(stream),它被實現(xiàn)為指向結構FILE的指針。

在啟動程序時,有三個文件流是自動打開的。他們是:

stdin: 標準輸入

stdout: 標準輸出

stderr: 標準錯誤輸出

下面會介紹一些常用的I/O庫函數(shù):

5.1 fopen函數(shù)

fopen函數(shù)類似于系統(tǒng)調(diào)用中的open函數(shù)。和open一樣,它返回文件的標識符,只是這里叫做流(stream),在庫函數(shù)里實現(xiàn)為一個指向文件的指針。

如果需要對設備的行為進行明確的控制,最好使用底層系統(tǒng)調(diào)用,因為這可以避免使用庫函數(shù)帶來的一些非預期的副作用,如輸入/輸出緩沖。

函數(shù)原型:

#include<stdio.h>

FILE *fopen(const char *filename, const char *mode);

參數(shù)說明:

*filename:打開文件的文件名

*mode:打開的方式

     r 以只讀方式打開文件,該文件必須存在。
  r+ 以可讀寫方式打開文件,該文件必須存在。
  rb+ 讀寫打開一個二進制文件,允許讀數(shù)據(jù)。
  rw+ 讀寫打開一個文本文件,允許讀和寫。
  w 打開只寫文件,若文件存在則文件長度清為0,即該文件內(nèi)容會消失。若文件不存在則建立該文件
  w+ 打開可讀寫文件,若文件存在則文件長度清為零,即該文件內(nèi)容會消失。若文件不存在則建立該文件。

fopen在成功是返回一個非空的FILE *指針。失敗返回NULL

5.2 fread/fwrite函數(shù)

fread函數(shù)從文件流中讀取數(shù)據(jù),對應于系統(tǒng)調(diào)用中的read;fwrite函數(shù)從文件流中寫數(shù)據(jù),對應于系統(tǒng)調(diào)用中的write

函數(shù)原型:

#include<stdio.h>

size_t  fread(void *ptr, size_t size, size_t nitems, FILE *stream);

參數(shù)說明:

*ptr 要讀取數(shù)據(jù)的緩沖區(qū),也就是要存放讀取數(shù)據(jù)的地方。

size:指定每個數(shù)據(jù)記錄的長度。

nitems: 計數(shù),給出要傳輸?shù)挠涗泜數(shù)。

返回值:成功讀取到數(shù)據(jù)緩沖區(qū)的記錄個數(shù),當?shù)竭_文件尾時,他的返回值可能會消耗與nitems,甚至可以是0

size_t  fwrite(const coid *ptr, size_t size , size_t nitimes, FILE *stream);

他從指定的數(shù)據(jù)緩沖區(qū)ptr中把數(shù)據(jù)寫入文件流,返回成功寫入的記錄個數(shù)。

5.3 fclose函數(shù)

fclose函數(shù)關閉指定的文件流stream,這個操作會使所有未寫出的數(shù)據(jù)都寫出。因為stdio庫函數(shù)會對數(shù)據(jù)進行緩沖,所有調(diào)用fclose函數(shù)是很重要的。

如果程序需要確保數(shù)據(jù)已經(jīng)全部寫出,就應該調(diào)用fclose函數(shù)。雖然程序正常結束時,也會自動的調(diào)用fclose函數(shù),但這樣就不能檢測出調(diào)用fclose所產(chǎn)生的錯誤了。

函數(shù)原型如下:

#include<stdio,h>

int fclose(FILE *stream);

5.4 fflush函數(shù)

fflush函數(shù)的作用是把文件流中所有未寫出的數(shù)據(jù)全部寫出。 處于效率考慮,在使用庫函數(shù)的時候會使用數(shù)據(jù)緩沖區(qū),當緩沖區(qū)滿的時候才進行寫操作。使用fflush函數(shù)

可以將緩沖區(qū)的數(shù)據(jù)全部寫出,而不關心緩沖區(qū)是否滿。fclose的執(zhí)行隱含調(diào)用了fflush函數(shù),所以不必再fclose執(zhí)行之前調(diào)用fflush。

函數(shù)原型:

#include<stdio.h>

int fflush(FILE *stream);

6 /proc文件系統(tǒng)

 Linux將一切看做文件,硬件設備在文件系統(tǒng)中也有相應的條目。/dev目錄中的文件使用底層系統(tǒng)調(diào)用這樣一種特殊方式來訪問硬件。

/proc文件系統(tǒng),可以看做是一個特殊的文件系統(tǒng),在這個系統(tǒng)中,每個文件都對應一個獨立的硬件,所以用戶可以通過proc文件系統(tǒng)像訪問文件一樣來訪問硬件設備。

該文件系統(tǒng)通常表現(xiàn)為/proc 目錄。該目錄中包含了許多特殊文件以允許對驅(qū)動和內(nèi)核信息進行高層訪問。

如果你想知道CPU的信息,內(nèi)核版本信息等,就可以通過proc文件系統(tǒng)。

/proc目錄中的文件會隨系統(tǒng)的不同而不同。我的電腦上的/proc 中的文件如下所示:

 在多數(shù)情況下,直接讀取這些文件就可以獲得狀態(tài)信息。

6.1 訪問設備信息

例如,獲取CPU的信息:

內(nèi)存使用信息(只顯示里局部~):

每次讀這些文件的內(nèi)容時,他們所提供的信息都會及時更新。所以再讀一次meminfo文件會得到不同的結果。

由特定內(nèi)核函數(shù)給出的更多信息可以在proc目錄的子目錄中查到。

6.2 查看內(nèi)核函數(shù)給出的信息

例如:查看網(wǎng)絡套接字的使用統(tǒng)計:

6.3通過proc查看進程信息

用ps 命令可得到當前正在運行的進程,每個進程在proc中都有相應的信息文件,通過查看這個文件,可以得知進程相關的信息:

進程2754的當前工作目錄是:/hme/yyl

程序 /bin/su正在運行,還有其他信息此處不再說明;

修改proc文件系統(tǒng)內(nèi)容

例如,系統(tǒng)中所有運行的程序同時打開的文件總數(shù)是Linux內(nèi)核的一個參數(shù)。

如果我們想要增大這個歌值,則可通過寫同一個文件來實現(xiàn)。

注意:對proc的寫操作要注意權限問題,在修改時要小心,不適當?shù)闹悼赡軙绊懙较到y(tǒng)的一運行。

    相關評論

    閱讀本文后您有什么感想? 已有人給出評價!

    • 8 喜歡喜歡
    • 3 頂
    • 1 難過難過
    • 5 囧
    • 3 圍觀圍觀
    • 2 無聊無聊

    熱門評論

    最新評論

    發(fā)表評論 查看所有評論(2)

    昵稱:
    表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
    字數(shù): 0/500 (您的評論需要經(jīng)過審核才能顯示)