版權(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度成都事業(yè)單位勞動(dòng)合同范本(含員工行為規(guī)范)
- 2025年度綠色能源PPP項(xiàng)目投資合作協(xié)議范本3篇
- Unit4SectionB2a-2e說(shuō)課稿2024-2025學(xué)年人教版英語(yǔ)八年級(jí)上冊(cè)
- 二零二五年度建筑工程施工合同:水渠硬化工程專(zhuān)業(yè)分包協(xié)議2篇
- 期末評(píng)估測(cè)試卷(二) (含答案)2024-2025學(xué)年數(shù)學(xué)冀教版八年級(jí)下冊(cè)
- 甘肅省甘南藏族自治州(2024年-2025年小學(xué)六年級(jí)語(yǔ)文)部編版摸底考試(上學(xué)期)試卷及答案
- 西藏那曲地區(qū)(2024年-2025年小學(xué)六年級(jí)語(yǔ)文)統(tǒng)編版階段練習(xí)((上下)學(xué)期)試卷及答案
- 貴州輕工職業(yè)技術(shù)學(xué)院《建筑外觀裝飾設(shè)計(jì)》2023-2024學(xué)年第一學(xué)期期末試卷
- 新疆巴音郭楞蒙古自治州(2024年-2025年小學(xué)六年級(jí)語(yǔ)文)部編版能力評(píng)測(cè)(下學(xué)期)試卷及答案
- 貴州農(nóng)業(yè)職業(yè)學(xué)院《明史趣談》2023-2024學(xué)年第一學(xué)期期末試卷
- 2023視頻監(jiān)控人臉識(shí)別系統(tǒng)技術(shù)規(guī)范
- 醫(yī)學(xué)教案SPZ-200型雙向道床配碴整形車(chē)操作保養(yǎng)維修手冊(cè)
- 2024年四川省宜賓市敘州區(qū)六年級(jí)數(shù)學(xué)第一學(xué)期期末監(jiān)測(cè)試題含解析
- 獸醫(yī)學(xué)英語(yǔ)詞匯【參考】
- 10《吃飯有講究》(教學(xué)設(shè)計(jì))-2024-2025學(xué)年道德與法治一年級(jí)上冊(cè)統(tǒng)編版
- 2024-2030年中國(guó)干燥設(shè)備行業(yè)研發(fā)創(chuàng)新?tīng)顩r及發(fā)展行情監(jiān)測(cè)研究報(bào)告
- 2024仁愛(ài)版新教材七年級(jí)上冊(cè)英語(yǔ)新課程內(nèi)容解讀課件(深度)
- 藥物生殖毒性研究技術(shù)指導(dǎo)原則
- 《UI界面設(shè)計(jì)》教案
- 食品技術(shù)咨詢(xún)服務(wù)
- 2023年浙江大學(xué)醫(yī)學(xué)院附屬邵逸夫醫(yī)院招聘考試真題及答案
評(píng)論
0/150
提交評(píng)論