這段時間正在研究LINUX的系統(tǒng)調(diào)用,用于本人喜歡把學過的東西整理起來,然后系統(tǒng)的去記憶。現(xiàn)在拿出來和大家分享。希望對像我這樣的初學者有所幫助。本文大部分內(nèi)容都是<Unix\Linux編程實踐教程> 這本書里的,加上一些自己的理解.
1.
名稱: open
目標: 打開一個文件。
頭文件: #include < fcntl.h>
函數(shù)原形: int fd=open(char * name,int how)
參數(shù): name 文件名
how 打開模式
返回值: -1 遇到錯誤
int 打開成功,返回文件描述符。
這個系統(tǒng)調(diào)用在進程和文件之間建立一條連接 ,這個連接被稱為文件描述符,它就像一條由進程通向內(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)機幫助中列出了各種可能的錯誤,大家可以看看。
UNIX允許一個文件被多個進程訪問,也就是說當一個文件被一個進程打開后,這個文件還可以被其它進程打開。
如果文件被順利打開內(nèi)核會返回一個正整數(shù)的值,這個數(shù)值就叫文件描述符,如果同時打開好幾個文件,它們所對應(yīng)的的文件描述符是不同的,如果一個文件打開多次,對應(yīng)的文件描述符也不相同。必須通過文件描述符對文件操作。下面的程序可以證明這一點。
#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
目標: 關(guān)閉一個文件。
頭文件: #include < unistd.h>
函數(shù)原形: int result=close(int fd)
參數(shù): fd 文件描述符
返回值: -1 遇到錯誤
int 關(guān)閉成功,返回文件描述符。
Close這個系統(tǒng)調(diào)用會關(guān)閉進程和文件fd之間的連接,如果關(guān)閉過程中出現(xiàn)錯誤,close返回-1,如:fd所指的文件并不存在。關(guān)閉成功則返回文件描述符。
3.
名稱: read
目標: 把數(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。
當文件的字節(jié)數(shù)沒有你想要的那么多時,read就會判斷下一個數(shù)值是不是’\0’,如果是就停止讀取,然后退出。numread返回的是’\0’之前的字節(jié)數(shù),也就是是原文件的字節(jié)數(shù)而不是你想讀的字節(jié)數(shù)。
4.
名稱: creat
目標: 創(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
目標: 將內(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)的措施。
學完上面幾個系統(tǒng)調(diào)用,我們就可以自己編寫的cp命令了。它的基本思路是從原文件讀取數(shù)據(jù)寫入緩沖,再將緩沖的數(shù)據(jù)寫入目標文件。
#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
目標: 使指針指向文件中的指定位置。
頭文件: #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=>當前位子
SEEK_END=>文件結(jié)束
返回值: -1 遇到錯誤
Ildpos 指針變化前的位子
Lseek改變文件描述符所關(guān)聯(lián)的指針的位置,新的位置由dist和base來指定,base是基準位置,dist是從基準位子開始的偏移量?;鶞饰蛔涌梢允俏募拈_始(0)、當前位子(1)或文件的結(jié)束(2)。例如:
lseek(fd,0,SEEK_END);