第十章系統級I/O
10.1 Unix I/O
一個檔案就是一個位元組序列。
所有的I/O裝置,如網絡、磁盤、和終端,都被模型化為檔案,而所有的輸入和輸出都被當做想對應的檔案的讀寫來執行。
這使得所有的輸入輸出都能以一種統一卻一緻的方式來執行
- 打開檔案
- 改變目前檔案位置
- 讀寫檔案
- 關閉檔案
10.2 打開和關閉檔案
程序是通過調用open函數來打開一個已存在的檔案或者建立一個新檔案的:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(char *filename, int flags, mode_t mode);
flags 參數 :
- O_RDONLY: Reading only
- O_WRONLY: Writing only
- O_RDWR: Reading and writing

#include <unistd.h>
int close(int fd);
10.3讀和寫檔案
應用程式是通過分别調用read和write函數來執行輸入和輸出的
應用程式是通過分别調用read和write函數來執行輸入和輸出的
讀檔案
include <unistd.h>
ssize_t read(int fd, void *buf, size_t n);//Returns: number of bytes read if OK, 0 on EOF, −1 on error
寫檔案
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t n);//Returns: number of bytes written if OK, −1 on error
10.4 用RIO包健壯的讀寫
可靠的讀
ssize_t rio_readn(int fd, void *usrbuf, size_t n) {
size_t nleft = n;
ssize_t nread;
char *bufp = usrbuf;
while (nleft > 0) {
if ((nread = read(fd, bufp, nleft)) < 0) {
}
if (errno == EINTR)
nread = 0;
else
return -1;
}
else if (nread == 0)
break;
nleft -= nread;
bufp += nread;
}
return (n - nleft);
}
可靠的寫 :
ssize_t rio_writen(int fd, void *usrbuf, size_t n)
size_t nleft = n;
ssize_t nwritten;
char *bufp = usrbuf;
while (nleft > 0) {
if ((nwritten = write(fd, bufp, nleft)) <= 0) {
if (errno == EINTR) /* Interrupted by sig handler return */
nwritten = 0;
else
return -1;
}
nleft -= nwritten;
bufp += nwritten;
}
return n; }
10.5 讀取檔案中繼資料
應用程式能夠通過調用stat和fstat函數,檢索到關于檔案的資訊。
10.6 共享檔案
核心用三個相關資料結構來表示打開的檔案
- 描述符表
- 檔案表
- v-node表
10.7 i/o重定向
unix提供重定向操作符,允許使用者将磁盤檔案和标準輸入輸出聯系起來
方法之一使用dup2函數
10.8 标準i/o
- ANSI C定義了一組進階輸入輸出函數,成為标準I/O庫,為程式員提供了Unix I/O的較進階别的替代。這個庫(libc)提供了打開和關閉檔案的函數(fopen和fclose)、讀和寫位元組的函數(fread和fwrite)、讀和寫字元串的函數(fgets和fputs)、以及複雜的格式化I/O函數(printf和scanf)。
使用标準I/O的好處
- 因為在出UNIX的很多作業系統(包括Windows, linux)上都實作了此庫,所有有利于軟體的移植。
與UnixI/O的主要差別
- UNIX I/O的函數都是針對檔案描述符的,而标準I/O的操作都是圍繞流進行的。所為的流就是一個FILE *
- 标準I/O提供了緩存--為了盡量減少write, read的調用。
- 标準I/O的效率會低一些,因為它是多了一層封裝。即,fread通過調用read來實作。
标準I/O的頭檔案
stdio.h
三個标準I/O流預定義指針:stdin, stdout, stderr
(Unix I/O: STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO)
10.9 綜合:我該使用哪些i/o函數
- 盡量隻使用标準I/O,而不要涉及低級的Unix I/O函數
- 建議在網絡套接字上不要使用标準I/O函數來進行輸入和輸出。而要使用健壯的RIO函數。
- 标準I/O流,從某種意義上來說是全雙工的,因為程式能夠在同一個流上執行輸入和輸出。
體會:本周的内容比較抽象,講的是系統級I/O。雖然内容不是很多,但是了解起來有些困難,是以閱讀了很多遍才了解其中的初級内容,如果要對這個有深入地了解還需要查閱更多的資料。
參考資料:
- 《深入了解計算機系統》課本第十章
- shangdahao 的部落格:http://www.cnblogs.com/shangdahao/archive/2013/04/14/3019461.html
- 行雲的部落格:http://www.cnblogs.com/uvsjoh/archive/2012/06/13/2547743.html