APUE:文件I/O
阿新 • • 發佈:2017-05-21
size nis position close ioctl ++ 標準 rect 追加
標準流描述符:
/* Standard file descriptors. */ #define STDIN_FILENO 0 /* Standard input. */ #define STDOUT_FILENO 1 /* Standard output. */ #define STDERR_FILENO 2 /* Standard error output. */
打開、創建、關閉文件:
#define O_ACCMODE 0003 /* O_ACCMODE = O_RDONLY | O_WRONLY | O_RDWR */ #define O_RDONLY 00 #define O_WRONLY 01 #define O_RDWR 02 #define O_CREAT 0100 /* open() 第 3 個參數指定權限位 */ #define O_EXCL 0200 #define O_NOCTTY 0400 #define O_TRUNC 01000 #define O_APPEND 02000 #define O_NONBLOCK 04000 /* 非阻塞 */ #define O_SYNC 04010000 #define O_FSYNC O_SYNC #define O_ASYNC 020000 #define O_DIRECTORY __O_DIRECTORY /* 打開非目錄出錯 */ #define O_NOFOLLOW __O_NOFOLLOW /* 打開符號鏈接出錯 */ #define O_CLOEXEC __O_CLOEXEC /* exec() 時關閉 */ int open (const char *__file, int __oflag, ...); int openat (int __fd, const char *__file, int __oflag, ...);
// open(__file, O_WRONLY | O_CREAT | O_TRUNC, __mode) int creat (const char *__file, mode_t __mode); int close (int __fd);
移動指針:
#define SEEK_SET 0 /* Seek from beginning of file. */ #define SEEK_CUR 1 /* Seek from current position. */ #define SEEK_END 2 /* Seek from end of file. */ __off_t lseek (int __fd, __off_t __offset, int __whence); __off64_t lseek64 (int __fd, __off64_t __offset, int __whence);
讀寫(註意原子操作):
ssize_t read (int __fd, void *__buf, size_t __nbytes); ssize_t pread (int __fd, void *__buf, size_t __nbytes, __off_t __offset); ssize_t write (int __fd, const void *__buf, size_t __n); ssize_t pwrite (int __fd, const void *__buf, size_t __n, __off_t __offset);
文件共享:
int dup (int __fd); int dup2 (int __fd, int __fd2); // 先關閉 fd2, 再復制 fd -> fd2
刷新內部緩沖:
void sync (void); // 只寫入隊列,不等待磁盤 I/O int fsync (int __fd); // 等待磁盤 I/O,更新數據和屬性 int fdatasync (int __fildes); // 等待磁盤 I/O,只更新數據
fcntl()和ioctl():
#define F_DUPFD 0 /* Duplicate file descriptor. */ #define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with close-on-exit set. */ #define F_GETFD 1 /* Get file descriptor flags. */ #define F_SETFD 2 /* Set file descriptor flags. */ #define F_GETFL 3 /* Get file status flags. */ #define F_SETFL 4 /* Set file status flags. */ #define F_SETOWN __F_SETOWN /* Get owner (process receiving SIGIO). */ #define F_GETOWN __F_GETOWN /* Set owner (process receiving SIGIO). */ int fcntl (int __fd, int __cmd, ...); int ioctl (int __fd, unsigned long int __request, ...);
/dev/fd:
每個進程看到的都不一樣,例如:
# ls -l /dev/fd/ > a.txt # cat a.txt total 0 lrwx------. 1 root root 64 May 20 16:34 0 -> /dev/pts/0 l-wx------. 1 root root 64 May 20 16:34 1 -> /root/a.txt lrwx------. 1 root root 64 May 20 16:34 2 -> /dev/pts/0 lr-x------. 1 root root 64 May 20 16:34 3 -> /proc/6259/fd
習題3.2 自己實現一個dup2():
int mydup2 (int fd, int fd2) { int fd_close[20] = { 0 }; int fd_temp; if(fd == fd2) { return fd2; } close(fd2); while((fd_temp = dup(fd)) != fd2) { fd_close[fd_temp] = 1; } for(int i = 0; i < (sizeof fd_close / sizeof fd_close[0]); i ++) { if(fd_close[i]) { close(i); } } return fd2; }
習題3.3 考慮下邊代碼,顯然 fd1 和 fd2 指向同一個 vnode:
#include <stdio.h> #include <fcntl.h> #include <unistd.h> int main(void) { int fd11 = open("a.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); int fd12 = dup(fd11); int fd21 = open("a.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); // abcdefg write(fd11, "abcdefg", 7); lseek(fd11, 0, SEEK_SET); // xxxxxxx write(fd12, "xxxxxxx", 7); // xxxxxxxyyyyyyy lseek(fd21, 0, SEEK_END); write(fd21, "yyyyyyy", 7); // xxxxxxxaaaaaaa write(fd11, "aaaaaaa", 7); return 0; }
習題3.6 以下代碼說明可以任意位置讀,寫入總在尾部追加:
#include <stdio.h> #include <fcntl.h> #include <unistd.h> int main(void) { char buffer[4] = { 0 }; int fd = open("a.txt", O_RDWR | O_CREAT | O_TRUNC | O_APPEND, 0644); write(fd, "abcdefg", 7); lseek(fd, 2, SEEK_SET); printf("%d\n", read(fd, buffer, 3)); printf("%s\n", buffer); printf("%d\n", write(fd, "xxx", 3)); return 0; }
APUE:文件I/O