基本看完了《unix/linux編程實踐教程》,實現了幾個小項目,覺得很不過瘾,書中對很多system call的細節和原理都沒講。在嘗試看linux內核分析的書時發現很多困難,所以拿起apue,繼續打基礎。讀著讀著,對apue上瘾了。這是題外話,就說這麼多。
相關閱讀:
UNIX系統編程小結(二)------文件和目錄 http://www.linuxidc.com/Linux/2012-12/75689.htm
Unix/Linux編程實踐教程【高清PDF中文版+附錄光盤+代碼】:http://www.linuxidc.com/Linux/2011-08/41374.htm
一.我對文件I/O的理解
文件I/O最基本的兩個函數就是read和write,書中也叫做unbuffered I/O。剛看到這個"unbuffered",我就奇怪,操作系統不是對所有的輸入輸出都會做緩存嗎(delayed write),為什麼還會存在unbuffered?但接著我就明白了,這裡的ubuffered,是指的是針對與read和write本身來說,他們是沒有緩存機制,比如read(fd,temp,100),在讀夠100個字節後或者遇到文件EOF後就返回,非常單純。而C庫函數中的fread和fwrite,就是利用緩存技術來調用read和write,可以說是buffered I/O。
二.文件描述符
文件描述符是一個整型,可以理解為一個指向文件的指針(注:整型也可以理解為一個指針,並不是只有void*才可以被叫做指針)。需要注意的就是,一個進程在結束的時候會關閉所有打開的文件描述符,但是0,1,2除外。0,1,2,分別代表標准輸入流,標准輸出流和標准錯誤流。這3個文件描述符是由kernel打開和進行管理的,不需要我們來打開和關閉。
三.文件共享機制
比較重要的就是file table的理解。file table包括了file status flags,the current file offset,a pointer to the v-node table entry for the file.比如對文件temp,調用一次open後,有fd1指向temp,也就有了一個file table。再對temp調用一次open後,有fd2指向temp,再生成一個file table(可以用dup,dup2實現,但又有不同,見下文)。這時,排除其他因素,我們的系統中有一個temp文件,2個文件描述符:fd1,fd2,兩個file table(表示同一個文件)。需要注意的是,如果對write操作加上了排他鎖,就無法用O_WRONLY同時打開兩個文件描述符了。但可以用O_RDONLY同時打開兩個文件描述符,fd1,fd2可以同時讀,而相應的,fd1指向的file table的current file offset自然可以不同於fd2指向的,這也就可以很容易地理解多個file table的作用了。
四.system call原理與分析
我喜歡用函數來總結所學的東西,感覺比較實在。
1.lseek(fd,5,SEEK_SET).修改current offset.返回新的offset.
2.open(file,O_RDWR).不贅述細節,詳見man。先寫一個問題,就是O_SYNC,我無法利用代碼來感受這個option,如果您能幫忙,小弟我非常感激。值得注意的就是O_APPEND,這個很強大的東西,跟>>重定向的"添加到末尾"是一樣的。特別注意,當open(file,O_RDWR | O_APPEND)後,write與read得到的待遇並不相同。每個被打開的文件都有一個current offset,可以用lseek對這個offset進行修改。先貼出代碼:
int main()
{
int fd;
char buf[100]="abcde";
//注:temp中只有一行aaaaabbbbbccccc.
if( (fd=open("temp",O_RDWR|O_APPEND))<0 )
err_sys("error open!");
if(lseek(fd,5,SEEK_SET)==-1)
err_sys("error lseek!");
if( read(fd,buf,5)<0 )
err_sys("error read!");
buf[5]='\0';
printf("%s\n",buf);
//if(write(fd,buf,5)!=5)
// err_sys("write error");
return 0;
}