1. unbuffered IO是相對于standard IO而言的,unbuffered指每個read和write函數(shù)都是通過內(nèi)核系統(tǒng)調(diào)用實現(xiàn)的。這些函數(shù)并不是ISO C的一部分,但都屬于POSIX.1和Single UNIX Specification.
2. File Descriptors
內(nèi) 核中所有打開的文件都是通過File Descriptor指向的。file descriptor是一個非負的整數(shù),按照管理,UNIX系統(tǒng)把0指定為進程的標準輸入,1為進程的標準輸出,2為標準錯誤輸出。為了程序的通用性考 慮,這些magic number應(yīng)該由<unistd.h>中的STDIN_FILENO, STDOUT_FILENO, STRERR_FILENO代替。
file descriptor的范圍是從[0, OPEN_MAX],早期系統(tǒng)的上限為19,現(xiàn)在許多已經(jīng)到達了63,Linux 2.4.22把每個進程打開的文件數(shù)上限提升到了2^20.
3. open 函數(shù)
#include <fcntl.h>
int open(const char *pathname, int oflag, ..., /* mode_t mode */ );
返回: 正常 - 最小的未被使用的file descriptor,出錯 - 0
oflag: O_RDONLY(0), O_WRONLY(1), O_RDWR(2) 括號內(nèi)為大多數(shù)情況下的值,這三個參數(shù)中必選一個,剩下的可選參數(shù)指定了是否追加、是否創(chuàng)建等信息,具體參見man 2 open
4. File Name and Pathname Truncation
如果創(chuàng)建的文件名長度大于NAME_MAX常量,BSD系統(tǒng)會返回一個錯誤狀態(tài),并把errno設(shè)為ENAMETOOLONG。如果只是把文件名截去部分就有可能導致與已存在的文件重名。
POSIX.1中的常量_POSIX_NO_TRUNC指定了長文件名和路徑會被截斷還是會引發(fā)錯誤
5. 創(chuàng)建文件
#include <fcntl.h>
int creat(const char *pathname, mode_t mode);
事實上這個函數(shù)等價于
open (pathname, O_WRONLY | O_CREAT | O_TRUNC, mode);
6. 關(guān)閉文件
#include <fcntl.h>
int close(int filedes);
返回: 成功 -1,出錯 0
當一個進程結(jié)束時,系統(tǒng)會自動關(guān)閉該進程打開的所有文件。
7. lseek 函數(shù)
每個打開的文件都有一個current file offset屬性,通常是一個非負的整數(shù)。默認情況下文件打開后該值為0,除非指定了O_APPEND選項。
#include <unistd.h>
off_t lseek(int filedes, off_t offset, int whence);
// Returns: new file offset if OK, -1 on error
可以通過seek 0字節(jié)來得到當前的offset
off_t currpos;
currpos = lseek(fd, 0, SEEK_CUR);
這個方法也可以用來判斷當前文件是否可以被seek,如果是指向管道(pipe),F(xiàn)IFO,或者socket的file descriptor,lseek把errno設(shè)置為ESPIPE并返回-1
某些設(shè)備可能允許負值的offset(如FreeBSD上的/dev/kmem),因此在檢查返回值時應(yīng)判斷是否等于-1,而不是是否小于0
2. File Descriptors
內(nèi) 核中所有打開的文件都是通過File Descriptor指向的。file descriptor是一個非負的整數(shù),按照管理,UNIX系統(tǒng)把0指定為進程的標準輸入,1為進程的標準輸出,2為標準錯誤輸出。為了程序的通用性考 慮,這些magic number應(yīng)該由<unistd.h>中的STDIN_FILENO, STDOUT_FILENO, STRERR_FILENO代替。
file descriptor的范圍是從[0, OPEN_MAX],早期系統(tǒng)的上限為19,現(xiàn)在許多已經(jīng)到達了63,Linux 2.4.22把每個進程打開的文件數(shù)上限提升到了2^20.
3. open 函數(shù)
#include <fcntl.h>
int open(const char *pathname, int oflag, ..., /* mode_t mode */ );
返回: 正常 - 最小的未被使用的file descriptor,出錯 - 0
oflag: O_RDONLY(0), O_WRONLY(1), O_RDWR(2) 括號內(nèi)為大多數(shù)情況下的值,這三個參數(shù)中必選一個,剩下的可選參數(shù)指定了是否追加、是否創(chuàng)建等信息,具體參見man 2 open
4. File Name and Pathname Truncation
如果創(chuàng)建的文件名長度大于NAME_MAX常量,BSD系統(tǒng)會返回一個錯誤狀態(tài),并把errno設(shè)為ENAMETOOLONG。如果只是把文件名截去部分就有可能導致與已存在的文件重名。
POSIX.1中的常量_POSIX_NO_TRUNC指定了長文件名和路徑會被截斷還是會引發(fā)錯誤
5. 創(chuàng)建文件
#include <fcntl.h>
int creat(const char *pathname, mode_t mode);
事實上這個函數(shù)等價于
open (pathname, O_WRONLY | O_CREAT | O_TRUNC, mode);
6. 關(guān)閉文件
#include <fcntl.h>
int close(int filedes);
返回: 成功 -1,出錯 0
當一個進程結(jié)束時,系統(tǒng)會自動關(guān)閉該進程打開的所有文件。
7. lseek 函數(shù)
每個打開的文件都有一個current file offset屬性,通常是一個非負的整數(shù)。默認情況下文件打開后該值為0,除非指定了O_APPEND選項。
#include <unistd.h>
off_t lseek(int filedes, off_t offset, int whence);
// Returns: new file offset if OK, -1 on error
可以通過seek 0字節(jié)來得到當前的offset
off_t currpos;
currpos = lseek(fd, 0, SEEK_CUR);
這個方法也可以用來判斷當前文件是否可以被seek,如果是指向管道(pipe),F(xiàn)IFO,或者socket的file descriptor,lseek把errno設(shè)置為ESPIPE并返回-1
某些設(shè)備可能允許負值的offset(如FreeBSD上的/dev/kmem),因此在檢查返回值時應(yīng)判斷是否等于-1,而不是是否小于0