




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、1嵌入式改變未來!Linux高級編程(一)張勇濤2什么是操作系統(tǒng)? 操作系統(tǒng)的定義: 操作系統(tǒng)是管理電腦硬件與軟件資源的程序,同時(shí)也是計(jì)算機(jī)系統(tǒng)的內(nèi)核與基石。操作系統(tǒng)是控制其他程序運(yùn)行,管理系統(tǒng)資源并為用戶提供操作界面的系統(tǒng)軟件的集合。操作系統(tǒng)身負(fù)諸如管理與配置內(nèi)存、決定系統(tǒng)資源供需的優(yōu)先次序、控制輸入與輸出設(shè)備、操作網(wǎng)絡(luò)與管理文件系統(tǒng)等基本事務(wù)。操作系統(tǒng)扮演的兩個(gè)角色:1. 魔術(shù)師角色2. 管理者角色3用戶程序和操作系統(tǒng)的關(guān)系 操作系統(tǒng)為用戶程序提供了一個(gè)虛擬機(jī)器界面,而應(yīng)用程序運(yùn)行在這個(gè)界面之上。 程序和程序之間的關(guān)系:無非是調(diào)用和被調(diào)用的關(guān)系。4文件文件I/OI/O操作操作5LINUX操
2、作系統(tǒng)的體系結(jié)構(gòu)6系統(tǒng)調(diào)用 系統(tǒng)調(diào)用就是用在程序中調(diào)用操作系統(tǒng)所提供的一些子功能 指操作系統(tǒng)提供給用戶程序的一組“特殊”接口,用戶程序可以通過這組“特殊”接口來獲得操作系統(tǒng)內(nèi)核提供的特殊服務(wù)。7系統(tǒng)調(diào)用所謂系統(tǒng)調(diào)用是指操作系統(tǒng)提供給用戶程序調(diào)用的一組“特殊”接口,用戶程序可以通過這組“特殊”接口來獲得操作系統(tǒng)內(nèi)核提供的服務(wù)。例如用戶可以通過進(jìn)程控制相關(guān)的系統(tǒng)調(diào)用來創(chuàng)建進(jìn)程、實(shí)現(xiàn)進(jìn)程調(diào)度、進(jìn)程管理等。為什么用戶程序不能直接訪問系統(tǒng)內(nèi)核提供的服務(wù)呢?這是由于在Linux中,為了更好地保護(hù)內(nèi)核空間,將程序的運(yùn)行空間分為內(nèi)核空間和用戶空間(也就是常稱的內(nèi)核態(tài)和用戶態(tài)),它們分別運(yùn)行在不同的級別上,在邏
3、輯上是相互隔離的。因此,用戶進(jìn)程在通常情況下不允許訪問內(nèi)核數(shù)據(jù),也無法使用內(nèi)核函數(shù),它們只能在用戶空間操作用戶數(shù)據(jù),調(diào)用用戶空間的函數(shù)。但是,在有些情況下,用戶空間的進(jìn)程需要獲得一定的系統(tǒng)服務(wù)(調(diào)用內(nèi)核空間程序),這時(shí)操作系統(tǒng)就必須利用系統(tǒng)提供給用戶的“特殊接口”系統(tǒng)調(diào)用規(guī)定用戶進(jìn)程進(jìn)入內(nèi)核空間的具體位置。進(jìn)行系統(tǒng)調(diào)用時(shí),程序運(yùn)行空間需要從用戶空間進(jìn)入內(nèi)核空間,處理完后再返回到用戶空間。 8用戶編程接口 API 前面講到的系統(tǒng)調(diào)用并不是直接與程序員進(jìn)行交互的,它僅僅是一個(gè)通過軟中斷機(jī)制向內(nèi)核提交請求,以獲取內(nèi)核服務(wù)的接口。在實(shí)際使用中程序員調(diào)用的通常是用戶編程接口API 系統(tǒng)命令相對API更高
4、了一層,它實(shí)際上一個(gè)可執(zhí)行程序,它的內(nèi)部引用了用戶編程接口(API)來實(shí)現(xiàn)相應(yīng)的功能。 9用戶編程接口(API) 系統(tǒng)調(diào)用并不直接與程序員進(jìn)行交互,它僅僅通過軟中斷的形式向內(nèi)核提交請求,以獲得內(nèi)核服務(wù)的接口. 用戶編程接口(API)其實(shí)是一個(gè)函數(shù)定義,說明了如何獲得一個(gè)給定的服務(wù)。 在linux中用戶編程接口(API)遵循了在UNIX中最流行的應(yīng)用編程界面標(biāo)準(zhǔn)POSIX標(biāo)準(zhǔn)。這些系統(tǒng)調(diào)用編程接口主要通過C庫(libc)實(shí)現(xiàn)的。10系統(tǒng)命令 系統(tǒng)命令實(shí)際上是可執(zhí)行程序.11系統(tǒng)調(diào)用、API、系統(tǒng)命令的關(guān)系12errno無論什么時(shí)候系統(tǒng)調(diào)用失敗了,都將errno設(shè)置成一組預(yù)定義的錯誤值中的一個(gè).s
5、trerror( ): 功能:以字符串方式打印錯誤信息。 用法: #include char *strerror(int errnum); 返回:指向消息字符串的指針。perror() 功能:在標(biāo)準(zhǔn)錯誤上產(chǎn)生一條基于其參數(shù)串和errno的當(dāng)前值出錯消息。 用法: #include void perror(const char * msg); 輸出:首先輸出由msg指向的字符串,然后是一個(gè)冒號,一個(gè)空格,然后是對應(yīng)于errno值的出錯信息,然后是一個(gè)新行符。13perror和strerror例子Perror例子:int main()FILE *fp;if(fp=fopen(1.txt,r) =
6、NULL) perror(fopen);exit(0); perror(fopen); fopen: No such file or directoryfopen: SuccessStrerror例子:main() int i; for(i=0;i10;i+) printf(“%d : %sn”,i,strerror(i);執(zhí)行 :0 : Success1 : Operation not permitted2 : No such file or directory3 : No such process4 : Interrupted system call5 : Input/output err
7、or6 : Device not configured7 : Argument list too long8 : Exec format error9 : Bad file descriptor備注:好像共有132個(gè)14UNIX哲學(xué)之一:一切皆為文件 Linux文件種類:1. 普通文件2. 目錄文件3. 鏈接文件4. 設(shè)備文件15文件描述符內(nèi)核如何區(qū)分和引用特定的文件呢?這里用到了一個(gè)重要的概念文件描述符。對于Linux而言,所有對設(shè)備和文件的操作都是使用文件描述符來進(jìn)行的。文件描述符是一個(gè)非負(fù)的整數(shù),它是一個(gè)索引值,并指向在內(nèi)核中每個(gè)進(jìn)程打開文件的記錄表。當(dāng)打開一個(gè)現(xiàn)存文件或創(chuàng)建一個(gè)新文件時(shí)
8、,內(nèi)核就向進(jìn)程返回一個(gè)文件描述符;當(dāng)需要讀寫文件時(shí),也需要把文件描述符作為參數(shù)傳遞給相應(yīng)的函數(shù)。通常,一個(gè)進(jìn)程啟動時(shí),都會打開3個(gè)文件:標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)出錯處理。這3個(gè)文件分別對應(yīng)文件描述符為0、1和2(也就是宏替換STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO)。包含在文件描述符的范圍是0 OPEN_MAXLinux 下OPEN_MAX為1048576 16底層文件I/O操作 open()函數(shù)是用于打開或創(chuàng)建文件,在打開或創(chuàng)建文件時(shí)可以指定文件的屬性及用戶的權(quán)限等各種參數(shù)。 close()函數(shù)是用于關(guān)閉一個(gè)被打開的文件。當(dāng)一個(gè)進(jìn)程終止時(shí),所有被它打開
9、的文件都由內(nèi)核自動關(guān)閉,很多程序都使用這一功能而不顯示地關(guān)閉一個(gè)文件。 read()函數(shù)是用于將從指定的文件描述符中讀出的數(shù)據(jù)放到緩存區(qū)中,并返回實(shí)際讀入的字節(jié)數(shù)。若返回0,則表示沒有數(shù)據(jù)可讀,即已達(dá)到文件尾。讀操作從文件的當(dāng)前指針位置開始。當(dāng)從終端設(shè)備文件中讀出數(shù)據(jù)時(shí),通常一次最多讀一行。 write()函數(shù)是用于向打開的文件寫數(shù)據(jù),寫操作從文件的當(dāng)前指針位置開始。對磁盤文件進(jìn)行寫操作,若磁盤已滿或超出該文件的長度,則write()函數(shù)返回失敗。 lseek()函數(shù)是用于在指定的文件描述符中將文件指針定位到相應(yīng)的位置。17open#include #include #include int
10、open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode); 返回值:成功返回新分配的文件描述符,出錯返回-1并設(shè)置errno18參數(shù)含義 pathname是要打開或創(chuàng)建的文件的名字。 oflag參數(shù)可用來說明此函數(shù)的多個(gè)選擇項(xiàng)。 mode 對于open函數(shù)而言,僅當(dāng)創(chuàng)建新文件時(shí)才使用第三個(gè)參數(shù)。 以下三個(gè)常數(shù)中必須指定一個(gè),且僅允許指定一個(gè)(這些常數(shù)定義在頭文件中): O_RDONLY 只讀打開。 O_WRONLY 只寫打開。 O_RDWR 讀、寫打開。19可選項(xiàng)以
11、下可選項(xiàng)可以同時(shí)指定0個(gè)或多個(gè), 和必選項(xiàng)按位或起來作為flags參數(shù)。 O_APPEND 每次寫時(shí)都加到文件的尾端。 O_CREAT 若此文件不存在則創(chuàng)建它。使用此選擇項(xiàng)時(shí),需同時(shí)說明第三個(gè)參數(shù)mode,用其說明該新文件的存取許可權(quán)位。 O_EXCL 如果同時(shí)指定了O_CREAT,而文件已經(jīng)存在,則出錯。這可測試一個(gè)文件是否存在,如果不存在則創(chuàng)建此文件成為一個(gè)原子操作。 O_TRUNC 如果此文件存在,而且為只讀或只寫成功打開,則將其長度截短為0。 O_NONBLOCK 如果pathname指的是一個(gè)塊特殊文件或一個(gè)字符特殊文件,則此選擇項(xiàng)為此文件的本次打開操作和后續(xù)的I / O操作設(shè)置非阻
12、塞方式。20mode第三個(gè)參數(shù)mode指定文件權(quán)限,可以用八進(jìn)制數(shù)表示,比如0644表示-rw-r-r-,也可以用S_IRUSR、S_IWUSR等宏定義按位或起來表示。mode取值含義S_IRUSR文件所有者的讀權(quán)限S_IWUSR文件安所有者的寫權(quán)限S_IXUSR文件所有者的執(zhí)行權(quán)限S_IRGRP文件所有者同組用戶的讀權(quán)限S_IWGRP文件所有者同組用戶的寫權(quán)限S_IXGRP文件所有者同組用戶的執(zhí)行權(quán)限S_IROTH其他用戶的讀權(quán)限S_IWOTH其他用戶的寫權(quán)限S_IXOTH其他用戶的執(zhí)行權(quán)限21creat 功能:創(chuàng)建一個(gè)新文件 用法: #include #include #include i
13、nt creat(const char *name, mode_t mode) ; 返回: 成功為只寫打開的文件描述符;出錯為-1。 出錯時(shí)errno被設(shè)置。 注意:此函數(shù)等效于: open (name, O_WRONLYO_CREATO_TRUNC, mode) ;creat函數(shù)現(xiàn)在已經(jīng)很少使用22close可用close函數(shù)關(guān)閉一個(gè)打開文件:#include int close (int filedes);返回:若成功為0,若出錯為- 1當(dāng)一個(gè)進(jìn)程終止時(shí),它所有的打開文件都由內(nèi)核自動關(guān)閉。很多程序都使用這一功能而不顯式地用c l o s e關(guān)閉打開的文件。23練習(xí): 打開文件./hello
14、.txt 用于寫操作,以追加方式打開 打開文件./hello.txt 用于寫操作,如果該文件不存在則創(chuàng)建 打開文件./hello.txt 用于寫操作,如果該文件已存在則截?cái)嗨?如果該文件不存在則創(chuàng)建它 打開文件./hello.txt 用于寫操作,如果該文件已存在則報(bào)錯退出,如果不存在則創(chuàng)建它24例子 打開文件test.txt 例子open.c25例子 打開文件的出錯情況 例子:file_error.c26read函數(shù) 用read函數(shù)從打開文件中讀數(shù)據(jù)#include ssize_t read(int feledes, void *buff, size_t nbytes) ;返回:讀到的字節(jié)數(shù),
15、若已到文件尾為0,若出錯為- 1。 如read成功,則返回讀到的字節(jié)數(shù)。如已到達(dá)文件的尾端,則返回0。read 從當(dāng)前文件偏移量處讀入指定大小的文件內(nèi)容。27實(shí)際讀到的字節(jié)數(shù)少于要求讀字節(jié)數(shù)1.讀普通文件時(shí),在讀到要求字節(jié)數(shù)之前已到達(dá)了文件尾端。例如,若在到達(dá)文件尾端之前還有30個(gè)字節(jié),而要求讀100個(gè)字節(jié),則read返回30,下一次再調(diào)用read時(shí),它將返回0 (文件尾端)。2. 當(dāng)從終端設(shè)備讀時(shí),通常一次最多讀一行。3. 當(dāng)從網(wǎng)絡(luò)讀時(shí),網(wǎng)絡(luò)中的緩沖機(jī)構(gòu)可能造成返回值小于所要求讀的字節(jié)數(shù)。28write函數(shù) 用write函數(shù)向打開文件寫數(shù)據(jù)。#include ssize_t write(in
16、t filedes, const void * buff, size_t nbytes) ;返回:若成功為已寫的字節(jié)數(shù),若出錯為- 1。其返回值通常與參數(shù)nbytes的值不同,否則表示出錯。write出錯的一個(gè)常見原因是:磁盤已寫滿,或者超過了對一個(gè)給定進(jìn)程的文件長度限制。29文件的讀寫操作 見例子my_cp.c30堵塞與非堵塞 讀常規(guī)文件是不會堵塞的,不管讀多少字節(jié),read一定會在有限的時(shí)間內(nèi)返回. 從終端和網(wǎng)絡(luò)讀則不一定,如果終端輸入不足一行,read一個(gè)終端設(shè)備就會堵塞. 如果在open一個(gè)設(shè)備時(shí)指定了O_NONBLOCK, read和write就不會堵塞. 以read為例,如果 設(shè)備
17、沒有數(shù)據(jù)到達(dá)就返回-1,同時(shí)置errno位31非堵塞工作模式while(1) 非堵塞 read(設(shè)備1); if(設(shè)備1有數(shù)據(jù)到達(dá)) 處理數(shù)據(jù); 非堵塞 read(設(shè)備2); if(設(shè)備2有數(shù)據(jù)到達(dá)) 處理數(shù)據(jù); sleep(n); 32問題如何解決? select可以堵塞地同時(shí)監(jiān)視多個(gè)設(shè)備,還可以設(shè)定堵塞等待的超時(shí)時(shí)間從而圓滿的解決這個(gè)問題.33堵塞讀終端例子34非堵塞讀終端的例子35lseek函數(shù)#include #include off_t lseek(int filesdes, off_t offset, int whence) ;返回:若成功為新的文件位移,若出錯為- 1。對參數(shù)of
18、fset 的解釋與參數(shù)w h e n c e的值有關(guān)。若whence是SEEK_SET,則將該文件的位移量設(shè)置為距文件開始處offset 個(gè)字節(jié)。若whence是SEEK_CUR ,則將該文件的位移量設(shè)置為其當(dāng)前值加offset,offset可為正或負(fù)。若whence是SEEK_END ,則將該文件的位移量設(shè)置為文件長度加offset,offset可為正或負(fù)。36如何測試文件位移量若lseek成功執(zhí)行,則返回新的文件位移量,為此可以用下列方式確定一個(gè)打開文件的當(dāng)前位移量:off_t curr_pos;curr_pos = lseek(fd, 0, SEEK_CUR);一般從當(dāng)前文件偏移量處寫入
19、,但如果打開時(shí)使用了O_APPEND,那么無論當(dāng)前文件偏移量在哪里,都會移動到文件末尾寫入思考題:如何迅速創(chuàng)建一個(gè)大文件?37例子 見lseek.c38fcntl函數(shù)fcntl函數(shù)可以改變已經(jīng)打開文件的性質(zhì)。#include #include #include int fcntl(int fd, int cmd);int fcntl(int fd, int cmd, long arg);int fcntl(int fd, int cmd, struct flock *lock);返回:若成功則依賴于cmd(見下),若出錯為- 1。fcntl函數(shù)改變一個(gè)已打開的文件的屬性,可以重新設(shè)置讀、寫、追
20、加、非阻塞等標(biāo)志(這些標(biāo)志稱為File Status Flag),而不必重新open文件。39 fcntl函數(shù)的五種功能復(fù)制一個(gè)現(xiàn)存的描述符, 新文件描述符作為函數(shù)值返(cmd = F_DUPFD)。 獲得/設(shè)置文件描述符標(biāo)記,對應(yīng)于filedes 的文件描述符標(biāo)志作為函數(shù)值返回(cmd = F_GETFD或F_SETFD)。 獲得/設(shè)置文件狀態(tài)標(biāo)志,對應(yīng)于filedes 的文件狀態(tài)標(biāo)志作為函數(shù)值返回。(cmd = F_GETFL或F_SETFL)。 獲得/設(shè)置異步I / O有權(quán)(cmd = F_GETOWN或F_SETOWN)。 獲得/設(shè)置記錄鎖(cmd = F_SETLK , F_SETL
21、KW)。40fcntl例子 用fcntl改變File Status Flag的例子41fcntl的作用 通過fcntl設(shè)置的都是當(dāng)前進(jìn)程如何設(shè)置訪問設(shè)備和文件的訪問控制屬性,如讀、寫、追加、非堵塞、加鎖等 但是不設(shè)置文件或設(shè)備本身的屬性,例如文件的讀寫權(quán)限、串口波特率等。42ioctl用于向設(shè)備發(fā)控制或配置命令。#include /* SVR4 */#include /* 4.3+BSD * /int ioctl(int filedes, int request, . . . ) ;返回:若出錯則為- 1,若成功則為其他值。43ioctl的特點(diǎn)ioctl 函數(shù)是I/O操作的雜物箱。不能用本章中
22、其他函數(shù)表示的I / O操作通常都能用ioctl表示。終端I/O是ioctl 的最大使用方面(POSIX.1已經(jīng)用新的函數(shù)代替ioctl進(jìn)行終端I / O操作)。ioctl更多的是用于設(shè)備控制,比如磁盤的格式化,MODEM設(shè)備,磁帶的快進(jìn)、快倒等。ioctl甚至可以讀寫一些數(shù)據(jù),但是這些數(shù)據(jù)是不能用read、write讀寫的,稱為out-of-band數(shù)據(jù).readwrite讀寫的是in-band數(shù)據(jù),是I/O操作的主體,而ioctl命令傳送的是控制信息,其中的數(shù)據(jù)是輔助的數(shù)據(jù).44ioctl例子 見ioctl例子45mmap#include void *mmap(void *addr, si
23、ze_t len, int prot, int flag, int filedes, off_t off); int munmap(void *addr, size_t len);mmap可以把磁盤文件的一部分直接映射到內(nèi)存,這樣文件中的位置直接就有對應(yīng)的內(nèi)存地址,對文件的讀寫可以直接用指針來做而不需要read/write函數(shù)46mmap函數(shù)47mmap 如果addr參數(shù)為NULL,內(nèi)核會自己在進(jìn)程地址空間中選擇合適的地址建立映射。 如果addr不是NULL,則給內(nèi)核一個(gè)提示,應(yīng)該從什么地址開始映射,內(nèi)核會選擇addr之上的某個(gè)合適的地址開始映射。 建立映射后,真正的映射首地址通過返回值可以得
24、到。len參數(shù)是需要映射的那一部分文件的長度。off參數(shù)是從文件的什么位置開始映射,必須是頁大小的整數(shù)倍(在32位體系統(tǒng)結(jié)構(gòu)上通常是4K)。filedes是代表該文件的描述符。48PROT_EXEC表示映射的這一段可執(zhí)行,例如映射共享庫PROT_READ表示映射的這一段可讀PROT_WRITE表示映射的這一段可寫PROT_NONE表示映射的這一段不可訪問flag參數(shù)有很多種取值,這里只講兩種,其它取值可查看mmap(2)MAP_SHARED多個(gè)進(jìn)程對同一個(gè)文件的映射是共享的,一個(gè)進(jìn)程對映射的內(nèi)存做了修改,另一個(gè)進(jìn)程也會看到這種變化。MAP_PRIVATE多個(gè)進(jìn)程對同一個(gè)文件的映射不是共享的,一
25、個(gè)進(jìn)程對映射的內(nèi)存做了修改,另一個(gè)進(jìn)程并不會看到這種變化,也不會真的寫到文件中去。如果mmap成功則返回映射首地址,如果出錯則返回常數(shù)MAP_FAILED。當(dāng)進(jìn)程終止時(shí),該進(jìn)程的映射內(nèi)存會自動解除,也可以調(diào)用munmap解除映射。munmap成功返回0,出錯返回-1。prot參數(shù)有四種取值:49mmap例子50文件截?cái)?include #include int truncate(const char *path, off_t length);int ftruncate(int fd, off_t length);truncate中path表示文件的路徑 length表示將文件截?cái)嗟淖止?jié)數(shù)截?cái)嗟?/p>
26、例子見truncate.c51sync #include int fsync(int filedes) 把指定文件的數(shù)據(jù)和屬性寫入到磁盤。 int fdatasync(int filedes) 把指定文件的數(shù)據(jù)部分寫到磁盤。 void sync(void) 把修改部分排入磁盤寫隊(duì)列,但并不意味著已經(jīng)寫入磁盤。52文件同步 見fsyn.c53文件和目錄操作的系統(tǒng)函數(shù) chmod chown mkdir/rmdir chdir/getcwd54文件讀寫作業(yè)text1.txtbegin10 11 1220 21 2230 31 32endtext2.txtbegin15 16 1725 26 273
27、5 36 37endtext3.txtbegin25 27 2945 47 4965 67 69end手動創(chuàng)建兩個(gè)文本文件text1.txt,text2.txt,要求編程創(chuàng)建text3.txt,實(shí)現(xiàn)text1.txt和text2.txt文件中除去首行和末尾對應(yīng)的數(shù)據(jù)相加,三個(gè)文本的內(nèi)容如上55標(biāo)準(zhǔn)標(biāo)準(zhǔn)I/OI/O開發(fā)開發(fā)56文件:存儲在外部介質(zhì)上數(shù)據(jù)的集合,是操作系統(tǒng)數(shù)據(jù)管 理的單位。文件分類: 按文件的邏輯結(jié)構(gòu):記錄文件:由具有一定結(jié)構(gòu)的記錄組成(定長和不定長)。流式文件:由一個(gè)個(gè)字符(字節(jié))數(shù)據(jù)順序組成。 按存儲介質(zhì):普通文件:存儲介質(zhì)文件(磁盤、磁帶等)。設(shè)備文件:非存儲介質(zhì)(鍵盤、顯示
28、器、打印機(jī)等)。 按數(shù)據(jù)的組織形式:ASCII文件(文本文件):每個(gè)字節(jié)存放ASCII碼,表示一個(gè)字符。二進(jìn)制文件:數(shù)據(jù)按其在內(nèi)存中的存儲形式原樣存放。C語言文件概述57文件類型 文件可分為文本文件(Text File)和二進(jìn)制文件(Binary File)兩種 源文件是文本文件,而目標(biāo)文件、可執(zhí)行文件和庫文件是二進(jìn)制文件。 od -tx1 -tc -Ax filename58例:整數(shù)100000010011100010000內(nèi)存存儲形式0010011100010000二進(jìn)制形式0011000100110000001100000011000000110000ASCII形式文本文件特點(diǎn):存儲量大
29、,轉(zhuǎn)換為二進(jìn)制速度慢,直觀易記。二進(jìn)制文件特點(diǎn):存儲量小,無需轉(zhuǎn)換。但因一個(gè)字節(jié)不對應(yīng)一個(gè)字符,故不能直接輸出其字符形式。59od命令 od (octal dump)和 xd(hexdump)命令可以以十進(jìn)制、八進(jìn)制、十六進(jìn)制和ASCII碼來顯示文件或者流,它們對于訪問或可視地檢查文件中不能直接顯示在終端上的字符很有用。 語法:od 選項(xiàng) 文件 命令中各選項(xiàng)的含義:- A 指定地址基數(shù),包括:d 十進(jìn)制o 八進(jìn)制(系統(tǒng)默認(rèn)值)x 十六進(jìn)制n 不打印位移值- t 指定數(shù)據(jù)的顯示格式,主要的參數(shù)有:c ASCII字符或反斜杠序列d 有符號十進(jìn)制數(shù)f 浮點(diǎn)數(shù)o 八進(jìn)制(系統(tǒng)默認(rèn)值為02)u 無符號十
30、進(jìn)制數(shù)x 十六進(jìn)制數(shù)除了選項(xiàng)c以外的其他選項(xiàng)后面都可以跟一個(gè)十進(jìn)制數(shù)n,指定每個(gè)顯示值所包含的字節(jié)數(shù)。60庫函數(shù)與系統(tǒng)調(diào)用的層次關(guān)系61打開文件fopen#include FILE *fopen(const char *path, const char *mode);返回值:成功返回文件指針,出錯返回NULL并設(shè)置errnopath是文件的路徑名,mode表示打開方式。62FILE FILE是C標(biāo)準(zhǔn)庫中定義的結(jié)構(gòu)體類型,其中包含該文件在內(nèi)核中標(biāo)識、I/O緩沖區(qū)和當(dāng)前讀寫位置等信息 像FILE *這樣的指針稱為不透明指針(Opaque Pointer)或者叫句柄(Handle),F(xiàn)ILE *指針
31、就像一個(gè)把手(Handle),抓住這個(gè)把手就可以打開門或抽屜,但用戶只能抓這個(gè)把手,而不能直接抓門或抽屜。63文件類型結(jié)構(gòu)體FILE 緩沖文件系統(tǒng)為每個(gè)正使用的文件在內(nèi)存開辟文件信息區(qū)。 文件信息用系統(tǒng)定義的名為FILE的結(jié)構(gòu)體描述。 FILE定義在stdio.h中。typedef struct short level; /* 緩沖區(qū)滿/空程度 */ unsigned flags; /* 文件狀態(tài)標(biāo)志 */ char fd; /* 文件描述符 */ unsigned char hold; /* 若無緩沖區(qū)不讀取字符 */ short bsize; /* 緩沖區(qū)大小 */ unsigned ch
32、ar *buffer; /* 數(shù)據(jù)傳送緩沖區(qū)位置 */ unsigned char *curp; /* 當(dāng)前讀寫位置 */ unsigned istemp; /* 臨時(shí)文件指示 */ short token; /* 用作無效檢測 */ FILE ; /* 結(jié)構(gòu)體類型名 FILE */FILE64 FILE *文件結(jié)構(gòu)指針名; 用法: 文件打開時(shí),系統(tǒng)自動建立文件結(jié)構(gòu)體,并把指向它的指針返回來,程序通過這個(gè)指針獲得文件信息,訪問文件。 文件關(guān)閉后,它的文件結(jié)構(gòu)體被釋放。文件名文件使用方式文件類型指針C程序操作系統(tǒng)磁盤FILE *fp;FILE65mode mode參數(shù)是一個(gè)字符串,由rwatb+
33、六個(gè)字符組合而成,r表示讀,w表示寫,a表示追加(Append),在文件末尾追加數(shù)據(jù)使文件的尺寸增大。 t表示文本文件,b表示二進(jìn)制文件,有些操作系統(tǒng)的文本文件和二進(jìn)制文件格式不同,而在UNIX系統(tǒng)中,無論文本文件還是二進(jìn)制文件都是由一串字節(jié)組成,t和b沒有區(qū)分,用哪個(gè)都一樣。66mode “r” :只讀,文件必須已存在 “w“:只寫,如果文件不存在則創(chuàng)建,如果文件已存在則把文件長度截?cái)啵═runcate)為0字節(jié)再重新寫,也就是替換掉原來的文件內(nèi)容 “a”:只能在文件末尾追加數(shù)據(jù),如果文件不存在則創(chuàng)建 “r+“:允許讀和寫,文件必須已存在 “w+“:允許讀和寫,如果文件不存在則創(chuàng)建,如果文件
34、已存在則把文件長度截?cái)酁?字節(jié)再重新寫 a+”:允許讀和追加數(shù)據(jù),如果文件不存在則創(chuàng)建67fopen的使用 在打開一個(gè)文件時(shí)如果出錯,fopen將返回NULL并設(shè)置errno。在程序中應(yīng)該做出錯處理,通常這樣寫:FILE *fp;if ( (fp = fopen(/tmp/file1, r) = NULL) perror(error open file /tmp/file1);exit(1);68fclose#include int fclose(FILE *fp);返回值:成功返回0,出錯返回EOF并設(shè)置errno磁盤文件輸出文件緩沖區(qū)輸入文件緩沖區(qū)程序數(shù)據(jù)區(qū)a緩沖文件系統(tǒng):fclose69
35、stdin/stdout/stderr UNIX的傳統(tǒng)是Everything is a file,鍵盤、顯示器、串口、磁盤等設(shè)備在/dev目錄下都有一個(gè)特殊的設(shè)備文件與之對應(yīng),這些設(shè)備文件也可以像普通文件一樣打開、讀、寫和關(guān)閉,使用的函數(shù)接口是相同的。那為什么printf和scanf不用打開就能對終端設(shè)備進(jìn)行操作呢?70練習(xí):打開一個(gè)沒有訪問權(quán)限的文件。fp = fopen(/etc/shadow, r);if (fp = NULL) perror(Open /etc/shadow);exit(1);fopen也可以打開一個(gè)目錄,傳給fopen的第一個(gè)參數(shù)目錄名末尾可以加/也可以不加/,但只允
36、許以只讀方式打開。試試如果以可寫的方式打開一個(gè)存在的目錄會怎么樣呢?fp = fopen(/home/zyt/, r+);if (fp = NULL) perror(Open /home/zyt);exit(1);71以字節(jié)為單位的I/O函數(shù)#include int fgetc(FILE *stream);int getchar(void);返回值:成功返回讀到的字節(jié),出錯或者讀到文件末尾時(shí)返回EOF從終端設(shè)備讀還有一個(gè)特點(diǎn),用戶輸入一般字符并不會使getchar函數(shù)返回,仍然阻塞著,只有當(dāng)用戶輸入回車或者到達(dá)文件末尾時(shí)getchar才返回72說明: 要用fgetc函數(shù)讀一個(gè)文件,該文件的打開
37、方式必須是可讀的。 系統(tǒng)對于每個(gè)打開的文件都記錄著當(dāng)前讀寫位置在文件中的地址(或者說距離文件開頭的字節(jié)數(shù)),也叫偏移量(Offset)。 fgetc成功時(shí)返回讀到一個(gè)字節(jié),本來應(yīng)該是unsigned char型的,但由于函數(shù)原型中返回值是int型,所以這個(gè)字節(jié)要轉(zhuǎn)換成int型再返回。73#include int fputc(int c, FILE *stream);int putchar(int c);返回值:成功返回寫入的字節(jié),出錯返回EOF74說明: 要用fputc函數(shù)寫一個(gè)文件,該文件的打開方式必須是可寫的(包括追加)。 每調(diào)用一次fputc,讀寫位置向后移動一個(gè)字節(jié),因此可以連續(xù)多次調(diào)
38、用fputc函數(shù)依次寫入多個(gè)字節(jié)。但如果文件是以追加方式打開的,每次調(diào)用fputc時(shí)總是將讀寫位置移到文件末尾然后把要寫入的字節(jié)追加到后面。75例子#include #include int main(void)FILE *fp;int ch;if ( (fp = fopen(file2, w+) = NULL) perror(Open file file2n);exit(1);while ( (ch = getchar() != EOF)fputc(ch, fp);rewind(fp);while ( (ch = fgetc(fp) != EOF)putchar(ch);fclose(fp)
39、;return 0;76練習(xí): 編寫一個(gè)簡單的文件復(fù)制程序。$ ./mycp dir1/fileA dir2/fileB運(yùn)行這個(gè)程序可以把dir1/fileA文件拷貝到dir2/fileB文件。 注意各種出錯處理。77操作讀寫位置的函數(shù)#include int fseek(FILE *stream, long offset, int whence);返回值:成功返回0,出錯返回-1并設(shè)置errnolong ftell(FILE *stream);返回值:成功返回當(dāng)前讀寫位置,出錯返回-1并設(shè)置errnovoid rewind(FILE *stream);78 fseek的whence和offs
40、et參數(shù)共同決定了讀寫位置移動到何處,whence參數(shù)的含義如下: SEEK_SET 從文件開頭移動offset個(gè)字節(jié) SEEK_CUR 從當(dāng)前位置移動offset個(gè)字節(jié) SEEK_END 從文件末尾移動offset個(gè)字節(jié)79以字符串為單位的I/O函數(shù)#include char *fgets(char *s, int size, FILE *stream);char *gets(char *s);返回值:成功時(shí)s指向哪返回的指針就指向哪,出錯或者讀到文件末尾時(shí)返回NULLfgets從指定的文件中讀一行字符到調(diào)用者提供的緩沖區(qū)中g(shù)ets從標(biāo)準(zhǔn)輸入讀一行字符到調(diào)用者提供的緩沖區(qū)中。80warning 1: gets函數(shù)的存在只是為了兼容以前的程序,我們寫的代碼都不應(yīng)該調(diào)用這個(gè)函數(shù)。gets函數(shù)的接口設(shè)計(jì)得很有問題,就像strcpy一樣,用戶提供一個(gè)緩沖區(qū),卻不能指定緩沖區(qū)的大小,很可能導(dǎo)致緩沖區(qū)溢出錯誤,這個(gè)函數(shù)比strcpy更加危險(xiǎn),strcpy的輸入和輸出都來自程序內(nèi)部,只要程序員小心一點(diǎn)就可以避免出問題,而gets讀取的輸入直接來自程序外部,用戶可能通過標(biāo)準(zhǔn)輸入提供任意長的字符串,程序員無法避免gets函數(shù)導(dǎo)致的緩沖區(qū)溢出錯誤,所以唯一的辦法就是不要用它。81w
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 出租 獨(dú)棟辦公屋合同范本
- 興義養(yǎng)老院合同范本
- 劇場服裝租賃合同范本
- 2024年四川西南科技大學(xué)招聘考試真題
- 公司干股贈與合同范本
- 丙綸防水簡易合同范本
- 買房 就業(yè)合同范本
- 充電樁居間合同范本
- 中式車間設(shè)備采購合同范本
- 代加工材料合同范本
- 2.2學(xué)會管理情緒 課件 -2024-2025學(xué)年統(tǒng)編版道德與法治七年級下冊
- 2025年湖北省技能高考(建筑技術(shù)類)《建筑材料與檢測》模擬練習(xí)試題庫(含答案)
- 七年級地理下冊 9.2 巴西說課稿 (新版)新人教版
- 人行道道鋪設(shè)施工方案
- 【歷史】元朝的建立與統(tǒng)一課件 2024-2025學(xué)年統(tǒng)編版七年級歷史下冊
- 2025年度游戲工作室游戲客服中心用工合同
- 2025湖北社會工作師歷年高頻重點(diǎn)提升(共500題)附帶答案詳解
- 橋梁拆除施工方案及安全措施
- 2024年吉林長春市總工會公招?聘工會社會工作者筆試真題
- 【歷史】2025年春季七下歷史新教材課本答案大全(想一想、材料研讀、讀地圖、課后活動)
- 2025中國煙草/中煙工業(yè)招聘高頻重點(diǎn)提升(共500題)附帶答案詳解
評論
0/150
提交評論