文件IO編程課件_第1頁(yè)
文件IO編程課件_第2頁(yè)
文件IO編程課件_第3頁(yè)
文件IO編程課件_第4頁(yè)
文件IO編程課件_第5頁(yè)
已閱讀5頁(yè),還剩50頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

,叢

本章的要求飛

?掌握Linux中系統(tǒng)調(diào)用的基本概念\

?掌握Linux中用戶(hù)編程接口(API)及系統(tǒng)

命令的相互關(guān)系

?掌握文件描述符的概念

?掌握Linux下文件相關(guān)的不帶緩存工/0函數(shù)

的使用

?掌握Linux下設(shè)備文件讀寫(xiě)方法

?熟悉Linux中標(biāo)準(zhǔn)文件工/0函數(shù)的使用

2

本章的主要內(nèi)容

Linux系統(tǒng)調(diào)用及用戶(hù)編程接口(AP工)

Linux中文件及文件描述符概述

底層文件工/。操作

嵌入式Linux串口應(yīng)用編程

標(biāo)準(zhǔn)工/0編程

實(shí)驗(yàn)

3

1Linux系統(tǒng)調(diào)用及用戶(hù)編程接口

(API)

4

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

?所謂系統(tǒng)調(diào)用是指操作系統(tǒng)提供給用戶(hù)程序調(diào)用的一組“特殊”

接口,用戶(hù)程序可以通過(guò)這組“特殊”接口來(lái)獲得操作系統(tǒng)內(nèi)核

提供的服務(wù)。(例如用戶(hù)可以通過(guò)進(jìn)程控制相關(guān)的系統(tǒng)調(diào)用來(lái)創(chuàng)

建進(jìn)程、實(shí)現(xiàn)進(jìn)程調(diào)度、進(jìn)程管理等。)

?為什么用戶(hù)程序不能直接訪問(wèn)系統(tǒng)內(nèi)核提供的服務(wù)呢?這是由于

在Linux中,為了更好地保護(hù)內(nèi)核空間,將程序的運(yùn)行空間分為

內(nèi)核空間和川戶(hù)空間(也就是常稱(chēng)的內(nèi)核態(tài)和用戶(hù)態(tài)),它

們分別運(yùn)行在不同的級(jí)別上,在邏輯上是相互隔離的。因此,ffl

戶(hù)進(jìn)程在通常情況下不允許訪問(wèn)內(nèi)核數(shù)據(jù),也無(wú)法使用內(nèi)核函數(shù),

它們只能在用戶(hù)空間操作用戶(hù)數(shù)據(jù),調(diào)用用戶(hù)空間的函數(shù)。

-但是,在有些情況下,用戶(hù)空間的進(jìn)程需要獲得一定的系統(tǒng)服務(wù)

(調(diào)用內(nèi)核空間程序),這時(shí)操作系統(tǒng)就必須利用系統(tǒng)提供給用

戶(hù)的“特殊接口”—系統(tǒng)調(diào)用規(guī)定用戶(hù)進(jìn)程進(jìn)入內(nèi)核空間的具

0進(jìn)行系統(tǒng)調(diào)用時(shí),程序運(yùn)行空間需要從用戶(hù)空間進(jìn)入內(nèi)

亥空間,處理完后再返回到用戶(hù)空間。

5

API

?前面講到的系統(tǒng)調(diào)用并不是直接與程序員進(jìn)行交互的,它僅僅是

一個(gè)通過(guò)軟中斷機(jī)制向內(nèi)核提交請(qǐng)求,以獲取內(nèi)核服務(wù)的接口。

在實(shí)際使用中程序員調(diào)用的通常是用戶(hù)編程接口一一API

?系統(tǒng)命令(如SHELL命令)相對(duì)API更高了一層,它實(shí)際上一個(gè)可

執(zhí)行程序,它的內(nèi)部引用了用戶(hù)編程接口(APD來(lái)實(shí)現(xiàn)相應(yīng)的

功能。

應(yīng)用程序

(系統(tǒng)命令,其他應(yīng)用程序)

用戶(hù)空間

用戶(hù)編程接口API

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

內(nèi)核空間

6

2Linux中文件及文件描述符概述

7

文件描述符

?Linux中的文件主要分為4種:普通文件、目錄文件、鏈接文件

和設(shè)備文件。

是使用文件描述符來(lái)進(jìn)行的。文件描述符是一個(gè)非負(fù)的整數(shù),它

是一個(gè)索弓值,并指向在內(nèi)核中每個(gè)進(jìn)程打開(kāi)文件的記錄表。當(dāng)

打開(kāi)一個(gè)現(xiàn)存文件或創(chuàng)建一個(gè)新文件時(shí),內(nèi)核就向進(jìn)程返回一個(gè)

文件描述錢(qián);當(dāng)責(zé)要讀寫(xiě)文件時(shí),也需要把文件描述符作為參數(shù)

傳遞給相應(yīng)的函數(shù)。

?通常,一人進(jìn)程啟動(dòng)時(shí),都會(huì)打開(kāi)3個(gè)文件:標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸

出和標(biāo)準(zhǔn)出錯(cuò)處理。這3個(gè)文件分別對(duì)應(yīng)文件描述符為0、1和2

(也就是宏替換STD工N_F1LENO、STDOUT_FILENOW

^STDERR.FILENO)o—一

8

?基于文件描述符的工/0操作雖然不能移植到類(lèi)Linux以外的系統(tǒng)

上去(如Windows),但它往往是實(shí)現(xiàn)某些工/O操作的惟一途徑,

如Linux中低級(jí)文件操作函數(shù)、多路工/0、TCP/工P套接字編程接

口等。同時(shí),它們也很好地兼容POS1X標(biāo)準(zhǔn),因此,可以很方

便地移植到任何POSJIX平臺(tái)上?;谖募枋龇墓?O操作是

Linux中最常用的操作之一。

?先來(lái)看看不帶緩存的"0和標(biāo)準(zhǔn)(帶緩存的)工/0都有那些

,不帶緩存的工/0:read,write,open....

,標(biāo)準(zhǔn)(帶緩存的)工/0:fgetszfreadzfwrite..…

?這里使用兩個(gè)對(duì)應(yīng)的函數(shù)進(jìn)行比較:

?ssize_twrite(intfiledes,constvoid*buffzsize_tnbytes)

,size_tfwrite(constvoid*ptr,size_tsize,size_tnobj,FILE

*fp)

?上面的buff和ptr都是指應(yīng)用程序自己使用的buffer,實(shí)際上

當(dāng)需要對(duì)文件丑行寫(xiě)操作時(shí),都會(huì)先寫(xiě)到內(nèi)核所設(shè)的緩沖存儲(chǔ)器。

再進(jìn)行實(shí)際的1/6操作,血就是此高于把數(shù)據(jù)黃正寫(xiě)到磁盤(pán),應(yīng)

種技未叫延遲寫(xiě)。

10

如果我們直接用非緩存工/。對(duì)內(nèi)核的緩沖區(qū)進(jìn)行讀寫(xiě),會(huì)產(chǎn)生許多管理

不善而造成的麻煩(如一次性寫(xiě)入過(guò)多,或多次系統(tǒng)調(diào)用導(dǎo)致的效率低

下)。

標(biāo)準(zhǔn)(帶緩存的)工/。為我們解決了這些問(wèn)題,它處理很多細(xì)節(jié),如緩沖

區(qū)分配,以?xún)?yōu)化長(zhǎng)度執(zhí)行工/0等,更便于我們使用。

由于標(biāo)準(zhǔn)(帶緩存的)工/0在系統(tǒng)調(diào)用的上一層多加了一個(gè)緩沖區(qū),也因

此引入了流的概念,在UN工X/Linux下表示為F工LE*(并不限于

UNIX/Linux,ANSIC都有FILE的概念),F(xiàn)ILE實(shí)際上包含了為管

理流所需要的所有信息:實(shí)際工/0的文件描述符,指向流緩存的指針

(標(biāo)準(zhǔn)工/0緩存,由malloc分配,又稱(chēng)為用戶(hù)態(tài)進(jìn)程空間的緩存,區(qū)別

于內(nèi)核所設(shè)的緩存),緩存長(zhǎng)度,當(dāng)前在緩存中的字節(jié)數(shù),出錯(cuò)標(biāo)志等。

-因此可知,不帶緩存的工/O對(duì)文件描述符操作,帶緩

G存的標(biāo)準(zhǔn)工/O是針對(duì)流的。

11

?標(biāo)準(zhǔn)工/0對(duì)每個(gè)工/O流自動(dòng)進(jìn)行緩存管理(標(biāo)準(zhǔn)工/。函數(shù)通常

調(diào)用malloc來(lái)分配緩存)。它提供了三種類(lèi)型的緩存:

?1)全緩存。當(dāng)填滿(mǎn)標(biāo)準(zhǔn)工/O緩存后才執(zhí)行工/O操作。磁盤(pán)上的

文件通常是全緩存的。

?2)行緩存。當(dāng)輸入輸出遇到新行符或緩存滿(mǎn)時(shí),才由標(biāo)準(zhǔn)工/O

庫(kù)執(zhí)行實(shí)際工/O操作。

,stdin、stdout通常是行緩存的。

,3)無(wú)緩存。相當(dāng)于read、writeTostderr通常是無(wú)緩存的,

同為它必須盡快輸出。

?一般而言,由系統(tǒng)選擇緩存的長(zhǎng)度,并自動(dòng)分配。標(biāo)準(zhǔn)工/0庫(kù)在

關(guān)閉流的時(shí)候自動(dòng)釋放緩存。

?另外,也可以使用函數(shù)fflush()將流所有未寫(xiě)的數(shù)據(jù)送入(刷新)

到內(nèi)核、(內(nèi)核緩沖區(qū)),fsync()將所有內(nèi)核緩沖區(qū)的數(shù)據(jù)寫(xiě)到

12

?在標(biāo)準(zhǔn)工/0庫(kù)中也有引入緩存管理而帶來(lái)的缺點(diǎn)一效率問(wèn)題。例

如當(dāng)使用每次一行函數(shù)fgets和fputs時(shí),通常需要復(fù)制兩次數(shù)

據(jù):一次是在內(nèi)核和標(biāo)準(zhǔn)工/0緩薦之間(當(dāng)調(diào)用rccicl和write

時(shí)),第二次是在標(biāo)準(zhǔn)工/0緩存(通常系統(tǒng)分配和管理)和用戶(hù)

程序中的行緩存(fgets的參數(shù)就需要一個(gè)用戶(hù)行緩存指針)之

間。

13

3不帶緩存的文件工/0操作

14

函數(shù)說(shuō)明

?open。函數(shù)是用于打開(kāi)或創(chuàng)建文件,在打開(kāi)或創(chuàng)建文件時(shí)可以指、

定文件的屬性及用戶(hù)的權(quán)限等各種參數(shù)。

?close。函數(shù)是用于關(guān)閉一個(gè)被打開(kāi)的文件。當(dāng)一個(gè)進(jìn)程終止時(shí),

所有被它打開(kāi)的文件都由內(nèi)核自動(dòng)關(guān)閉,很多程序都使用這一功

能而不顯不如關(guān)閏一個(gè)文件。

?read。函數(shù)是用于將從指定的文件描述符中讀出的數(shù)據(jù)放到緩存

區(qū)中,并返回實(shí)際讀入的字節(jié)數(shù)。若返回0,則表示沒(méi)有數(shù)據(jù)可

讀,即已達(dá)到文件尾。讀操作從文件的當(dāng)前指針位置開(kāi)始。當(dāng)從

終端設(shè)備文件中讀出數(shù)據(jù)時(shí),通常一次最多讀一行。

?write。函數(shù)是用于向打開(kāi)的文件寫(xiě)數(shù)據(jù),寫(xiě)操作從文件的當(dāng)前指

針位置開(kāi)始。對(duì)磁盤(pán)文件進(jìn)行寫(xiě)操作,若磁盤(pán)已滿(mǎn)或超出該文件

的長(zhǎng)度,則wr汁c()函數(shù)返回失敗。

?IscekO函數(shù)是用于在指定的文件描述符中將文件指針定位到相應(yīng)

的位置。它只能用在可定位(可隨機(jī)訪問(wèn))文件操作中。管道、

套接字和大部分字符設(shè)備文件是不可定位的,所以在這些文件的

口無(wú)法使用lscck()調(diào)用。

15

open。語(yǔ)法要點(diǎn)

#include<sys/types.h>/*提供類(lèi)型pid_t的定義%」

所需頭文件。#include<sys/stat.h>^

#include<fcntl.h>p

函數(shù)原型。intopen(constchar*pathname,intflags,intperms"

pathname*21被打開(kāi)的文件名(可包括路徑名)-

O_RDONLY:以只讀方式打開(kāi)文件。

O_WRONLY:以只寫(xiě)方式打開(kāi)文件Q

(J_RDWR:以讀寫(xiě)方式打開(kāi)文件,

O_CREAT:如果該文件不存在,就創(chuàng)建一個(gè)新的文件,并用第三個(gè)參

數(shù)為其設(shè)置權(quán)限

O_EXCL:如果使用。_CREAT時(shí)文件存在,則可返回錯(cuò)誤消息、。這一

flag:文件打套致可測(cè)試文件是否言。此時(shí)。pen是原子操作,防止多個(gè)進(jìn)程同時(shí)

開(kāi)的方式創(chuàng)建同一個(gè)文件。*

O.NOCTTY:使用本參數(shù)時(shí),若文件為終端,那么該終端不會(huì)成為調(diào)

函數(shù)傳入值。用open。的那個(gè)進(jìn)程的控制終端衰

O_TRUNC:若文件已經(jīng)存在,那么會(huì)刪除文件中的全部原有數(shù)據(jù),并

且設(shè)置文件大小為0。9

O_APPEND:以添加方式打開(kāi)文件,在打開(kāi)文件的同時(shí),文件指針指

向文件的末尾,即將寫(xiě)入的數(shù)據(jù)添加到文件的末尾。一

被打開(kāi)文件的存取權(quán)限。~

可以用一組宏定義:S_I(R/W/X)(USR/GRP/OTH>

其中R/WX分別表示讀/寫(xiě)秋行權(quán)限.

perms-

USR/GRP/OTH分別表示文件所有者/文件所屬組/其他用戶(hù)。~

例如SJRUSR|S」WUSR表示設(shè)置文件所有者的可讀可寫(xiě)屬性。八進(jìn)

制表示法中6。0也表示同樣的權(quán)限。-

16

成功:返回文件描述符,

函數(shù)返回值P

失?。?3

close。語(yǔ)法要點(diǎn)

所需頭文件2#include<unistd.h>*'

函數(shù)原型。intclose(intfd)<

函數(shù)輸入值一fd:文件描述符。

0:成功J

函數(shù)返回值一

-1:出錯(cuò)r

read。語(yǔ)法要點(diǎn)

所需頭文件。#include<unistd.h>^

函數(shù)原型一ssize_tread(intfd,void*buf,size_tcount*

fd:文件描述符“

函數(shù)傳入值qbuf:指定存儲(chǔ)器讀出數(shù)據(jù)的緩沖區(qū)2

count:指定讀出的字節(jié)數(shù)石

成功:讀到的字節(jié)數(shù)1

&函數(shù)返回值。0:已到達(dá)文件尾?

-1:出錯(cuò)二

write。語(yǔ)法要點(diǎn)

所需頭文件”#mclude<unistd.h>-

函數(shù)原型。ssize_twrite(intfd,void*buf,size_tcount)*

fd:文件描述符。

函數(shù)傳入值。buf:指定存儲(chǔ)器寫(xiě)入數(shù)據(jù)的緩沖區(qū)〃

count:指定讀出的字節(jié)數(shù),

成功:已寫(xiě)的字節(jié)數(shù),

函數(shù)返回值2

-1:出錯(cuò)一

lseek()語(yǔ)法要點(diǎn)

#include<unistd.h>^

所需頭文件“

#include<sys/types.h>^

函數(shù)原型Qoff_tlseek(intfd,off_toffset,intwhence)*3

fd:文件描述符.,

函數(shù)傳入值"offset:偏移量,每一讀寫(xiě)操作所需要移動(dòng)的距離,單位是字節(jié),可正可負(fù)(向

前移,向后移〉2

SEEK_SET:當(dāng)前位置為文件的開(kāi)頭,新位置為偏移量的大小,

whence:。SEEK_CUR:當(dāng)前位置為文件指針的位置,新位置為當(dāng)前位置加上

當(dāng)前位置偏移量2

的基點(diǎn)Q

SEEK_END:當(dāng)前位置為文件的結(jié)尾,新位置為文件的大小加上偏

移量的大小”

成功:文件的當(dāng)前位移1

函數(shù)返回值。

-1:出錯(cuò)/

實(shí)驗(yàn)1\

?基本功能:從一個(gè)文件(源文件,以只讀方式打開(kāi))

中讀取最后10KB數(shù)據(jù)并復(fù)制到另一個(gè)文件(目標(biāo)文件,

以只寫(xiě)方式打開(kāi))。如果目標(biāo)文件不存在,可以創(chuàng)建

并設(shè)置權(quán)限的初始值為644(文件所有者可讀可寫(xiě),

文件所屬組合其他用戶(hù)只能讀)。

19

#include<unistd.h>

#include<sys/types.h>

#include<sys/stat.h>

#include<fcntl.h>

#include<stdlib.h>

#include<stdio.h>

#defineBUFFER_SIZE1024

#defineSRC_FILE_NAME"/lib/libm.so.6"

#defineDEST_FILE_NAME"dest_file"

#defineOFFSET1024

intmain()

{

intsrc_fila,dest_file;

unsignedcharbuff[BUFFER_SIZE];

intreal_read_len;

src_file=open(SRC_FILE_NAME,0_RbONLy);

版馥㈱艘蔑犒NAME,WyQ,REATQRUSRlSJ

if(src_file<0||dest_file<0)

(

printf("Openfileerror\n");

exit(l);

}

lseak(src_file,-OFFSET,5EEK_END);

while((neal_read_len=nead(src_file/buff/sizeof(buff)))>0)

(

write(dest_file,buff^eaLreadJen);

)

close(dest_file);

close(src_file);

return0;

21

實(shí)驗(yàn)2

open函數(shù)帶有3個(gè)flag參數(shù):O_CREAT、O_TRUNC和

O_WRONLY,這樣就可以對(duì)不同的情況指定相應(yīng)的處理方法

22

實(shí)驗(yàn)3

open函數(shù)返回的文件描述符一定是最小的未用文件描述符。

由于一個(gè)進(jìn)程在啟動(dòng)時(shí)自動(dòng)打開(kāi)了0、1、2三個(gè)文件描述符,

因此,該文件運(yùn)行結(jié)果中返回的文件描述符為3。讀者可以嘗

試在調(diào)用open函數(shù)之前,加依據(jù)close(O),則此后在open函

數(shù)時(shí)返回的文件描述符為0

文件鎖個(gè)

?前面的這5個(gè)基本函數(shù)實(shí)現(xiàn)了文件的打開(kāi)、讀寫(xiě)等基本操才

這一節(jié)將討論的是,在文件已經(jīng)共享的情況下如何操作,

也就是當(dāng)多個(gè)用戶(hù)共同使用、操作一個(gè)文件的情況,這時(shí),

Linux通常采用的方法是給文件上鎖,來(lái)避免共享的資源

產(chǎn)生競(jìng)爭(zhēng)的狀態(tài)。

?文件鎖包括建議性鎖和強(qiáng)制性鎖。建議性鎖要求每個(gè)上鎖

文件的進(jìn)程都要檢查是否有鎖存在,并且尊重已有的鎖。

在一般情況下,內(nèi)核和系統(tǒng)都不使用建議性鎖。強(qiáng)制性鎖

是由內(nèi)核執(zhí)行的鎖,當(dāng)一個(gè)文件被上鎖進(jìn)行寫(xiě)入操作的時(shí)

候,內(nèi)核將阻止其他任何文件對(duì)其進(jìn)行讀寫(xiě)操作。采用強(qiáng)

制性鎖對(duì)性能的影響很大,每次讀寫(xiě)操作都必須檢查是否

有鎖存在。

24

?在Linux中,實(shí)現(xiàn)文件上鎖的函數(shù)有l(wèi)ockf()和fcntl(),其中

lockf()用于對(duì)文件施加建議性鎖,而fcntR)不僅可以施加

建議性鎖,還可以施加強(qiáng)制鎖。同時(shí),fcntl()還能對(duì)文件

的某一記錄上鎖,也就是記錄鎖。

?記錄鎖又可分為讀取鎖和寫(xiě)入鎖,其中讀取鎖又稱(chēng)為共享

鎖,它能夠使多個(gè)進(jìn)程都能在文件的同一部分建立讀取鎖。

而寫(xiě)入鎖又稱(chēng)為排斥鎖,在任何時(shí)刻只能有一個(gè)進(jìn)程在文

件的某個(gè)部分上建立寫(xiě)入鎖。當(dāng)然,在文件的同一部分不

能同時(shí)建立法取筋和寫(xiě)入鎖。

fcntl()函數(shù)格式(1)

J----------------------------------------------

#include<sys/types.h>?1

所需頭文件」#include<unistd.h>-

#include<fcntl.h>^

函數(shù)原型“intfcntl(intfd,mtcmd,structflock*lock)^

fd:文件描述符.、

F_DUPFD:復(fù)制文件描述符?

F_GETFD:獲得fd的close-on-exec標(biāo)志,君揚(yáng)常術(shù)設(shè)置,則文件經(jīng)過(guò)exec。函

?之后仍保持打開(kāi)狀態(tài)一

F_SETFD:設(shè)置close-on-exec標(biāo)志,該標(biāo)志由參數(shù)arg的FD_CLOEXEC位法庭:

F_GETFL:得到open設(shè)置的標(biāo)志”

函數(shù)傳入值?cm*

F_SETFL:改變open設(shè)置的標(biāo)志

F_GETLK:根據(jù)lock描述,決定是否上文件鎖“

F_SETLK:設(shè)置lock描述的文件鎖.、

F_SETLKW:這是F_SETLK的阻塞版本(命令名中的W表示等待(wait))

在無(wú)法獲取鎖時(shí),會(huì)進(jìn)入睡眠狀態(tài);如果可以獲取鉞逸煮捕捉到信號(hào)則會(huì)返回

1lock:結(jié)構(gòu)為flock,設(shè)置記錄鎖的具體狀態(tài),后面會(huì)詳細(xì)說(shuō)明2

成功:CU

函數(shù)返回值-

二-1:出錯(cuò)2

26

fcntl()函數(shù)格式(2)-

叫flock結(jié)構(gòu)

shortl_type;

off_tl_start;

shortl_whence;

off_tIJen;

pid_tl_pid;

F_RDLCK:讀取鎖(共享鎖〉P

FWRLCK:寫(xiě)入鎖(排斥鎖)

FliNLCK:解鎖q

相對(duì)位移量《字節(jié)》

SEEK_SET:當(dāng)前位置為文件的開(kāi)頭,新位置為偏移量的大小.,

會(huì)的起點(diǎn)(同keekSEEKCUR:當(dāng)前位置為文件指針的位置,新位置為當(dāng)前位置加上偏移量。

的whence)。

SEEK_ENI):當(dāng)前位置為文件的結(jié)尾,新位置為文件的大小加上偏移量的大小。

加他或麻葭

27

實(shí)驗(yàn)4

28

工/。處理的模型

?阻塞工/O模型:在這種模型下,若所調(diào)用的工/O函數(shù)沒(méi)有完成相

關(guān)的功能,則會(huì)使進(jìn)程掛起,直到相關(guān)數(shù)據(jù)到達(dá)才會(huì)返回。如常

見(jiàn)對(duì)管道設(shè)備、終端設(shè)備和網(wǎng)絡(luò)設(shè)備進(jìn)行讀寫(xiě)時(shí)經(jīng)常會(huì)出現(xiàn)這種

情況。(如實(shí)驗(yàn)4中的阻塞加鎖)

?非阻塞模型:在這種模型下,當(dāng)請(qǐng)求的1/0操作不能完成時(shí),則

不讓進(jìn)程睡眠,而且立即返回。非阻塞1/0使用戶(hù)可以調(diào)用不會(huì)

阻塞的1/0操作,如open。、write()ffread()o如果該操作不能

完成,則會(huì)立即返回出錯(cuò)(例如:打不開(kāi)文件)或者返回0(例

如:在緩沖區(qū)中沒(méi)有數(shù)據(jù)可以讀取或者沒(méi)空間可以寫(xiě)入數(shù)據(jù))。

29

?工/O多路轉(zhuǎn)接模型:在這種模型下,如果請(qǐng)求的工/。操作阻塞,

且它不是真正阻塞工/0,而是讓其中的一個(gè)函數(shù)等待,在這期間,

工/0還能進(jìn)行其他操作。如本節(jié)要介紹的select。和poll函數(shù)(),

就是屬于這種模型。

?信號(hào)驅(qū)動(dòng)]70模型:在這種模型下,通過(guò)安裝一個(gè)信號(hào)處理程序,

系統(tǒng)可以自動(dòng)捕獲特定信號(hào)的到來(lái),從而啟動(dòng)工/0。這是由內(nèi)核

通知用戶(hù)何時(shí)可以啟動(dòng)一個(gè)工/0操作決定的。

?異步工/O模型:在這種模型下,當(dāng)一個(gè)描述符已準(zhǔn)備好,可以啟

動(dòng)工/0時(shí),進(jìn)程會(huì)通知內(nèi)核?,F(xiàn)在,并不是所有的系統(tǒng)都支持這

種模型。

select。和poll。

?select。和poll。的工/O多路轉(zhuǎn)接模型是處理工/O復(fù)用

的一個(gè)高效的方法。它可以具體設(shè)置程序中每一個(gè)所

關(guān)心的文件描述符的條件、希望等待的時(shí)間等,從

select。和poll。函數(shù)返回時(shí),內(nèi)核會(huì)通知用戶(hù)已準(zhǔn)備

好的文件描述符的數(shù)量、已準(zhǔn)備好的條件等。通過(guò)使

用select。和poll。函數(shù)的返回結(jié)果,就可以調(diào)用相應(yīng)

的工/0處理函數(shù)了。

31

select。函數(shù)格式(1)

耳include<sys-hpes.li

所需頭文件”include<sxs/tiine.h?

麗chide<imistd1I>P

intselect(mtnunifds,fdsetlreadfds,fdset'xvntefds?-、

函數(shù)原型〃

fdset1cxeptfds.structtuneAal1timeout)*1

numfds:該參數(shù)值為需要監(jiān)視的文件描述符的最大值加IP

readfds:由select。監(jiān)視的讀文件描述符集合「

wiitefds:由select。監(jiān)視的寫(xiě)文件描述符集合/

exeptfds:由select。監(jiān)視的異常處理文件描述符集合

函數(shù)傳入值,

NULL:永遠(yuǎn)等待,直到捕捉到信號(hào)或文件描述符己準(zhǔn)備好為止”

何具體值:structtimeval類(lèi)型的指針,若等待了timeout時(shí)間還沒(méi)有檢測(cè)到

timeout“任何文件描符準(zhǔn)備好,就立即返回,

0:從不等待,測(cè)試所有指定的描述符并立即返回.,

成功:準(zhǔn)備好的文件描述符,

函數(shù)返回值2

0:超時(shí);-1:出錯(cuò)。

32

select。函數(shù)格式(2)

?select函數(shù)根據(jù)希望進(jìn)行的文件操作對(duì)文件描述符進(jìn)行了分類(lèi)處理,

這里,對(duì)文件描述符的處理主要涉及到4個(gè)宏函數(shù)

FD_ZERO(fd_set,lset)p清除一個(gè)文件描述符集「

FT)_SET(iiitfd,fdset將一個(gè)文件描述符加入文件描述符集中~

FD_CLR(iiitfd,fdset:l:set)*)將一個(gè)文件描述符從文件描述符集中清除。

如果文件描述符fd為fdset集中的一個(gè)元素,則返回非零值,可以

FD_ISSET(intfd,fdset*set).用于調(diào)用select。之后測(cè)試文件描述符集中的哪個(gè)文件描述符是否

有變化

?一般來(lái)說(shuō),在使用select。函數(shù)之前,首先使用FD_ZERO()和FD_SET()來(lái)初

始化文件描述符集,在使用了select。函數(shù)時(shí),可循環(huán)使用FD_JS§ET()來(lái)測(cè)試

描述符集,在執(zhí)行完對(duì)相關(guān)文件描述符的操作之后,使用FD_CLR()來(lái)清除描

述符集。

33

?另外,select函數(shù)中的timeout是一個(gè)structtimeval類(lèi)型的指針,

該結(jié)構(gòu)體如下所示:

,structtimeval{

?longtv_sec;/*second*/

?longtv_unsec;/*andmicroseconds*/

?}

?可以看到,這個(gè)時(shí)間結(jié)構(gòu)住的精確度可以設(shè)置到微秒級(jí),這對(duì)于

大多數(shù)的應(yīng)用而言已經(jīng)足似了。

poll。函數(shù)格式

#uichide<sy*types.h>“?

所需頭文件。

=iiichule'poll.li^

函數(shù)原型。iiitpoll(stiiictpollfd:,sfds,intnumfds、iiittimeout"

fds:stmctpollfd結(jié)構(gòu)的指針,用于描述需要對(duì)哪些文件的哪種類(lèi)型的操作進(jìn)行監(jiān)控….

structpollfd"

Ulffd:/*需要監(jiān)聽(tīng)的文件描述符

shoitevents;/*需要監(jiān)聽(tīng)的事件*/,

shortrevents:/*己發(fā)生的事件%

events成員描述需要監(jiān)聽(tīng)哪些類(lèi)型的事件,可以用以下幾種標(biāo)志來(lái)描述:~

函數(shù)傳入值”P(pán)OLLIN:文件中有數(shù)據(jù)可讀,下面實(shí)例中使用到了這個(gè)標(biāo)志~

POLLPRI::文件中有緊急數(shù)據(jù)可讀“

POLLOUT:可以向文件寫(xiě)入數(shù)據(jù).

POLLERR:文件中出現(xiàn)錯(cuò)誤,只限于輸出,

POLLHUP:與文件的連接被斷開(kāi)了,只限于輸出“

POLLNVAL:文件描述符是不合法的,即它并沒(méi)有指向一個(gè)成功打開(kāi)的文件。。

munfds:需要監(jiān)聽(tīng)的文件個(gè)數(shù),即第一個(gè)參數(shù)所指向的數(shù)組中的元素?cái)?shù)目。

timeout:表示poll阻塞的超時(shí)時(shí)間(毫秒)。如果該值小于等于0,則表示無(wú)限等待?!?/p>

成功:返回大于0的值,表示事件發(fā)生的pollfd結(jié)構(gòu)的個(gè)數(shù)?!?

函數(shù)返回值,

0:超時(shí);-1:出錯(cuò),

35

實(shí)驗(yàn)5select多路復(fù)用

36

4標(biāo)準(zhǔn)工/o編程

37

標(biāo)準(zhǔn)工/0編程概述

?前面講述的系統(tǒng)調(diào)用是操作系統(tǒng)直接提供的函數(shù)接口。因

為運(yùn)行系統(tǒng)調(diào)用時(shí),Linux必須從用戶(hù)態(tài)切換到內(nèi)核態(tài),執(zhí)

行相應(yīng)的請(qǐng)求,然后再返回到用戶(hù)態(tài),所以應(yīng)該盡量減少

系統(tǒng)調(diào)用的次數(shù),從而提高程序的效率。標(biāo)準(zhǔn)工/。提供流

緩沖的目的是盡可能減少使用read。和wri佗()等系統(tǒng)調(diào)用

的數(shù)量。標(biāo)準(zhǔn)工/O提供了3種類(lèi)型的緩沖存儲(chǔ)。

?全緩沖:在這種情況下,當(dāng)填滿(mǎn)標(biāo)準(zhǔn)"。緩存后才進(jìn)行實(shí)

際工/O操作。對(duì)于存放在磁盤(pán)上的文件通常是由標(biāo)準(zhǔn)工/O

庫(kù)實(shí)施全緩沖的。

38

?行緩沖:在這種情況下,當(dāng)在輸入和輸出中遇到行結(jié)束符時(shí),標(biāo)

準(zhǔn)工/0庫(kù)執(zhí)行工/0操作。這允許我們一次輸出一個(gè)字符(如

fputc()函數(shù)),但只有寫(xiě)了一行之后才進(jìn)行實(shí)際工/0操作。標(biāo)準(zhǔn)

輸入和標(biāo)準(zhǔn)輸出就是使用行緩沖的典型例子。

?不帶緩沖:標(biāo)準(zhǔn)工/0庫(kù)不對(duì)字符進(jìn)行緩沖。如果用標(biāo)準(zhǔn)工/0函數(shù)

寫(xiě)若干字符到不帶緩沖的流中,則相當(dāng)于用系統(tǒng)調(diào)用wMteO函數(shù)

將這些字符全寫(xiě)到被打開(kāi)的文件上。標(biāo)準(zhǔn)出錯(cuò)stderr通常是不帶

緩存的,這就使得出錯(cuò)信息可以盡快顯示出來(lái),而不管它們是否

含有一個(gè)行結(jié)束符。

39

基本操作(1)

?打開(kāi)文件:

有三個(gè)標(biāo)準(zhǔn)函數(shù),分別為:fopen()>fdopen()和

freopenQo它們可以以不同的模式打開(kāi),但都返

回一個(gè)指向F工LE的指針,該指針指向?qū)?yīng)的1/0

流。此后,對(duì)文件的讀寫(xiě)都是通過(guò)這個(gè)F工LE指針

所需頭文件,wichide<stdio.li>43

函數(shù)原型。FILEfopen(constchai*path,constchar1mode)*

Path:包含要打開(kāi)的文件路徑及文件名-

函數(shù)傳入值/

mode:文件打開(kāi)狀態(tài)(后面會(huì)具體說(shuō)明)。

成功:指向FILE的指針,

函數(shù)返回值2

失?。篘ULL,

40

基本操作(2)

其中,mode定義打開(kāi)文件的訪問(wèn)權(quán)限等:

r或山+、打開(kāi)只讀文件,該文件必須存在。

r+或r+b。打開(kāi)可讀寫(xiě)的文件,該文件必須存在e

打開(kāi)只寫(xiě)文件,若文件存在則文件長(zhǎng)度清為0,即會(huì)擦寫(xiě)文件以前的內(nèi)容。若文件不

W或wbp

存在則建立該文件。

打開(kāi)可讀寫(xiě)文件,若文件存在則文件長(zhǎng)度清為0,即會(huì)擦寫(xiě)文件以前的內(nèi)容。若文件

\v+或w+b:

不存在則建立該文件。

以附加的方式打開(kāi)只寫(xiě)文件。若文件不存在,則會(huì)建立該文件;如果文件存在,寫(xiě)

a或ab+>

入的數(shù)據(jù)會(huì)被加到文件尾,即文件原先的內(nèi)容會(huì)被保留?

以附加方式打開(kāi)可讀寫(xiě)的文件。若文件不存在,則會(huì)建立該文件;如果文件存在,

a+或a+b~

寫(xiě)入的數(shù)據(jù)會(huì)被加到文件尾后,即文件原先的內(nèi)容會(huì)被保留,

基本操作(3)

?關(guān)閉文件:

關(guān)閉標(biāo)準(zhǔn)流文件的函數(shù)為fclose(),該函數(shù)將緩

沖區(qū)內(nèi)的數(shù)據(jù)全部寫(xiě)入到文件中,并釋放系統(tǒng)所

提供的文件資源。

所需頭文件a箱nch*le<stdio.li>*3

函數(shù)原型。uitfcloselFILE4stream)/

函數(shù)傳入值“stream:己打開(kāi)的文件指針"

成功:Ox

函數(shù)返回值

失?。篍OF。

基本操作(4)

?在文件流祓打開(kāi)夕后,向?qū)ξ募髦v行

所需頭文件,如chide<stdio.h中

函數(shù)原型一sizetfiead(Aoidph,size_tsize,size」iunenib,FILE1stream*

pti:存放讀入記錄的緩沖區(qū)。

size:讀取的記錄大小e

函數(shù)傳入值。

nmemb:讀取的記錄數(shù)

stream:要讀取的文件流。

成功:返回實(shí)際讀取到的mnemb數(shù)目x

函數(shù)返回值2

失敗:EOFP

43

基本操作(5)

所需頭文件,國(guó)iclude<stdio.h>^

函數(shù)原型。sizetfwrite(constvoid*ptr、size_tsize,sizetnniemb、FILE*stream)*'

Ptl:存放寫(xiě)入記錄的緩沖區(qū)2

size:寫(xiě)入的記錄大小"

函數(shù)傳入值“i

muemb:寫(xiě)入的記錄數(shù)。

stream:要寫(xiě)入的文件流2

成功:返回實(shí)際寫(xiě)入到的luiiemb數(shù)目A

函數(shù)返回值

失?。篍OF'

示例

?閱讀代碼并運(yùn)行示例6-5-1

45

其他操作(1)

所需頭文件a施chide<stdio.li>*3

uitpntc(iiitc.FILE*stream)】

函數(shù)原型「uitc,FILE*stream),

iiitputchaijmtC)P

成功:字符小

函數(shù)返回值。

失敗:EOF。

字符輸出函數(shù)

所需頭文件2include<stdio.li>*5

uitgetc(FILE1stream)】

函數(shù)原型「uitfgetcfFILE*stream"

uitgetcliar(voi(l)<

函數(shù)傳入值2stream:要輸入的文件流+,

成功:下一個(gè)字符?

函數(shù)返回值。

失敗:EOF*,

46

其他操作(2)

行輸入函數(shù)

所需頭文件。#include<$tdioh>^

chargets(chai*s)i

函數(shù)原型,

charfgets(chai1s.intsize.FILE*stream”

8:要輸入的字符串1

函數(shù)傳入值Csize:輸入的字符串長(zhǎng)度i

stream:對(duì)應(yīng)的文件流“

成功:S,

函數(shù)返回值。

失?。篘ULL,

?行輸出函數(shù)

所需頭文件delude<stdio.h>,)

iiitputs(constchar*S)Ag

函數(shù)原型。

mtfputs(coustchar*s,FTT.F*stream*\

8:要輸出的字符串,\

函數(shù)傳入值,sheam:對(duì)應(yīng)的文件流a,

成功:si\

函數(shù)返回值“

失敗:NULL,J

47

其它操作(3)-格式化輸入

所需頭文件include<stdio.li><3

intconstchar"format…

函數(shù)原型QintfjJiintRFELEconstchai*foimat...)i

uitspiiiitf(chai*buf.constchai:,cfonnat...)P

format:記錄輸出格式,

函數(shù)傳入值。fp:文件描述符,

buf:記錄輸出緩沖區(qū)Q

成功:輸出字符數(shù)(spdntf返回存入數(shù)組中的字符數(shù)):

函數(shù)返回值。

失?。篘ULL-

強(qiáng)chide<stdaig.li>!

所需頭文件,

?chide<stdioh>.

iiit、"printf(constchar1fonnat.va_listarg)J

函數(shù)原型“uitAfpiiiitf(FILE*fp,constchar:「formatva_listarg)J

uitvsprintf(char'buf,constchai:,:foiinatva_listarg)^

fonnat:記錄輸出格式J

函數(shù)傳入值。fj):文件描述符二

arg:相關(guān)命令參數(shù)a

成功:存入數(shù)組的字符數(shù)】

函數(shù)返回值

失敗:NULL-

48

其它操作(4)-格式化輸入

輸出(2)

所需頭文件2筠include<stdio.h>p'/

intscanf(constchai*fbnnat,...)A,「

函數(shù)原型「inffscaiif(HLE"邳、constchar*fbnnat…),i

uitsscaiififchai:hbuf,constchar*format,\

foimat:記錄輸出格式i、)

函數(shù)傳入值2m:文件描述符Jr

buf:記錄輸入緩沖區(qū)。Y

成功:輸出字符數(shù)(spnutf返回存入數(shù)組中的字符數(shù))i,1

函數(shù)返回值。

失?。篘ULL.,f

49

6.6實(shí)驗(yàn)

50

實(shí)驗(yàn)1-文件讀寫(xiě)及上鎖(1)

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論