|
Linux系統(tǒng)調(diào)用(一)—文件讀寫操作 這段時間正在研究LINUX的系統(tǒng)調(diào)用,用于本人喜歡把學(xué)過的東西整理起來,然后系統(tǒng)的去記憶?,F(xiàn)在拿出來和大家分享。希望對像我這樣的初學(xué)者有所幫助。本文大部分內(nèi)容都是<Unix\Linux編程實踐教程> 這本書里的,加上一些自己的理解.
1. 名稱: open 目標(biāo): 打開一個文件。 頭文件: #include < fcntl.h> 函數(shù)原形: int fd=open(char * name,int how) 參數(shù): name 文件名 how 打開模式 返回值: -1 遇到錯誤 int 打開成功,返回文件描述符。 這個系統(tǒng)調(diào)用在進(jìn)程和文件之間建立一條連接 ,這個連接被稱為文件描述符,它就像一條由進(jìn)程通向內(nèi)核的管道?! ?br> 要打開一個文件,必須指定文件名和打開模式,有3種打開模式:只讀,只寫,可讀可寫,分別對應(yīng)于O_RDONLY,O_WRONLY,O_RDWR,這在頭文件/usr/include/fcntl.h中有定義。 打開文件是內(nèi)核提供的服務(wù),如果在打開過程中內(nèi)核檢測到任何錯誤,這個系統(tǒng)調(diào)用就會返回-1。錯誤的類型是各種各樣的,如:要打開的文件不存在。即使文件存在可能因為權(quán)限不夠而無法打開,在open的聯(lián)機(jī)幫助中列出了各種可能的錯誤,大家可以看看。 UNIX允許一個文件被多個進(jìn)程訪問,也就是說當(dāng)一個文件被一個進(jìn)程打開后,這個文件還可以被其它進(jìn)程打開。 如果文件被順利打開內(nèi)核會返回一個正整數(shù)的值,這個數(shù)值就叫文件描述符,如果同時打開好幾個文件,它們所對應(yīng)的的文件描述符是不同的,如果一個文件打開多次,對應(yīng)的文件描述符也不相同。必須通過文件描述符對文件操作。下面的程序可以證明這一點。
CODE:
#include <stdio.h>
#include <fcntl.h> #include <unistd.h> int main(int ac,char *av[]) /*int ac是命令行參數(shù)的個數(shù). char *argv[]是一個存放字符指針的數(shù)組, 每個指針指向一個具體的命令行參數(shù)(字符串)*/ { int fd; int size; char buf[10000]; /*定義用于存放數(shù)據(jù)的目的緩沖區(qū)*/ if(ac==1) printf(“please input file!\n”); else { while(--ac) { printf(“file :%s\n”,av[ac]); fd=open(av[1],O_RDONLY); printf(“fd:%d\n”,fd); size=read(fd,buf,sizeof(buf)); printf(“size:%d\n”,size); printf(“%s”,buf); } close(fd); return -1; } } 我們編譯一下 [root@LINUX root]# cc –o show_read show_read.c 運行 [root@LINUX root]# ./show_read show_read.c 下面是運行結(jié)果。 file: 3 size:423 #include <stdio.h> …… 我們可以看出此次打開文件的文件描述符是3,如果我們執(zhí)行下面的語句。 [root@LINUX root]# ./show_read show_read.c show_read.c 下面是運行結(jié)果: file: 3 size: 423 #include <stdio.h> …… file: 4 size 432 #include <stdio.h> …… 可以看到,我們第一次打開文件的描述符是3,第二次打開文件的文件描述符是4。 2. 名稱: close 目標(biāo): 關(guān)閉一個文件。 頭文件: #include < unistd.h> 函數(shù)原形: int result=close(int fd) 參數(shù): fd 文件描述符 返回值: -1 遇到錯誤 int 關(guān)閉成功,返回文件描述符。 Close這個系統(tǒng)調(diào)用會關(guān)閉進(jìn)程和文件fd之間的連接,如果關(guān)閉過程中出現(xiàn)錯誤,close返回-1,如:fd所指的文件并不存在。關(guān)閉成功則返回文件描述符。 3. 名稱: read 目標(biāo): 把數(shù)據(jù)讀到緩沖區(qū)。 頭文件: #include < unistd.h> 函數(shù)原形: ssize_t numread=read(int fd, void *buf, size_t qty) 參數(shù): fd 文件描述符 buf 用來存放數(shù)據(jù)的目的緩沖區(qū) qty 要讀取的字節(jié)數(shù) 返回值: -1 遇到錯誤 unmread 成功關(guān)閉,返回所讀取的字節(jié)數(shù)目。 read這個系統(tǒng)調(diào)用請求內(nèi)核從fd所指定的文件中讀取qty字節(jié)的數(shù)據(jù),存放到buf所指定的內(nèi)存空間中,內(nèi)核如果成功地讀取了數(shù)據(jù),就返回所讀取的字節(jié)數(shù)目。否則返回-1。 當(dāng)文件的字節(jié)數(shù)沒有你想要的那么多時,read就會判斷下一個數(shù)值是不是’\0’,如果是就停止讀取,然后退出。numread返回的是’\0’之前的字節(jié)數(shù),也就是是原文件的字節(jié)數(shù)而不是你想讀的字節(jié)數(shù)。 4. 名稱: creat 目標(biāo): 創(chuàng)建/重寫一個文件 頭文件: #include < fcntl.h> 函數(shù)原形: int fd=creat(char *filename,node_t mode) 參數(shù): filename 文件名 mode 訪問模式 返回值: -1 遇到錯誤 fd 創(chuàng)建成功 Creat告訴內(nèi)核創(chuàng)建一個名為filename的文件,如果這個文件不存在,就創(chuàng)建它,如果已經(jīng)存在,就把它的內(nèi)容清空,把文件的長度設(shè)為0。 如果內(nèi)核成功地創(chuàng)建了文件,那么文件的許可位(permission bits)被設(shè)置為由第二個參數(shù)mode所指定的值.如: fd=creat(“addressbook”,0644); 創(chuàng)建一個名為addressbook的文件,如果文件不存在,那么文件的許可位被設(shè)為 rw-r-r—. 如果文件已存在它的內(nèi)容會被清空。任一情況下,fd都會是指向addressbook的文件描述符。 5. 名稱: write 目標(biāo): 將內(nèi)存中的數(shù)據(jù)寫入文件。 頭文件: #include < unistd.h> 函數(shù)原形: ssize_t numread=write(int fd, void *buf, size_t amt) 參數(shù): fd 文件描述符 buf 內(nèi)存數(shù)據(jù) amt 要寫的字節(jié)數(shù) 返回值: -1 遇到錯誤 Num written 成功寫入,返回寫入的字節(jié)數(shù)目。 在實際的寫入過程中,可能會出現(xiàn)寫入的字節(jié)數(shù)少于所要求的。這可能有兩個原因,第一是有的系統(tǒng)對文件的最大尺寸有限制,第二是磁盤空間接近滿了。在上述兩 種情況下內(nèi)核都會盡力把數(shù)據(jù)往文件中寫,并將實際寫入的字節(jié)數(shù)返回,所以調(diào)用write后都必須檢查返回值是否與要寫入的相同,如果不同就要采取相應(yīng)的措 施。 學(xué)完上面幾個系統(tǒng)調(diào)用,我們就可以自己編寫的cp命令了。它的基本思路是從原文件讀取數(shù)據(jù)寫入緩沖,再將緩沖的數(shù)據(jù)寫入目標(biāo)文件。
CODE:
#include <stdio.h>
#include <unistd.h> #include <fcntl.h> #define BUFFERSIZE 4096 #define COPYMODE 0644 void oops(char *s1,char *s2); main(int ac,char *av[]) { int in_fd,out_fd,n_chars; char buf[BUFFERSIZE]; if(ac!=3) { fprintf(stderr,”usage:%s source destination\n”,*av); exit(1); } if(in_fd=open(av[1],O_RDONLY))==-1) opps(“Cannot open”,av[1]); if(out_fd=creat(av[2], COPYMODE))==-1) oops(“Cannot creat”,av[2]); while((n_chars=read(in_fd,buf,BUFFERSIZE))>0) { if(write(out_fd,buf,n_chars)!=n_chars) oops(“Write error to”,av[2]); } if(n_chars==-1) opps(“Read error form”,av[1]); if(close(in_fd)==1||close(out_fd)==-1) opps(“Error clising files”,” ”); } Void oops(char *s1,char *s2) { fprintf(stderr,”Error:%s”s1); perror(s2); exit(1); } 6. 名稱:: lseek 目標(biāo): 使指針指向文件中的指定位置。 頭文件: #include <sys/type.h> #include <unistd.h> 函數(shù)原形: off_t oldpos = lseek(int fd,off_t dist,int base) 參數(shù): fd 文件描述符 dist 移動的距離 base SEEK_SET=>文件的開始 SEEK_CUR=>當(dāng)前位子 SEEK_END=>文件結(jié)束 返回值: -1 遇到錯誤 Ildpos 指針變化前的位子 Lseek改變文件描述符所關(guān)聯(lián)的指針的位置,新的位置由dist和base來指定,base是基準(zhǔn)位置,dist是從基準(zhǔn)位子開始的偏移量?;鶞?zhǔn)位子可以是文件的開始(0)、當(dāng)前位子(1)或文件的結(jié)束(2)。例如: lseek(fd,0,SEEK_END); |
|
|