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