1. 程式人生 > >檔案I/O相關函式

檔案I/O相關函式

open()和openat()函式:

#include <fcntl.h>

// 成功返回檔案描述符,出錯返回-1
int open(const char *path, int oflag, ... /* mode_t mode */);
int openat(int fd, const char *path, int oflag, ... /* mode_t mode */);
int creat(const char *path, mode_t mode);
// creat()因為歷史原因,作為彌補open()不能開啟一個尚未存在的檔案的這個缺憾而存在
// 而隨著opne()提供了O_CREAT和O_TRUNC之後就不需要creat()函數了
// mode引數在開啟一個不存在的檔案時(建立新檔案)需要指定 // path引數為絕對路徑: fd引數被忽略,open()與openat()效果相同 // path引數為相對路徑: fd為該相對路徑的起始地址 // openat()函式實際上就是為了可以使用相對路徑開啟目錄中的檔案和避免TOCTTOU錯誤產生的

mode引數的值有點類似與建立IPC物件所用的mode常值,但有點區別,以下時open()使用的mode值:
S_IRUSR 使用者讀
S_IWUSR 使用者寫
S_IXUSR 使用者執行
S_IRGRP 組讀
S_IWGRP 組寫
S_IXGRP 組執行
S_IROTH 其他使用者讀
S_IWOTH 其他使用者寫
S_IXOTH 其他使用者執行

oflag引數取值:
O_RDONLY, O_WRONLY, or O_RDWR
可選值
O_APPEND, O_CLOEXEC, O_CREAT, O_DIRECTORY, O_EXCL, O_NOCTTY, O_NOFOLLOW, O_NONBLOCK,
O_SYNC, O_TRUNC, O_TTYINIT
同樣的函式,在Linux上的實現及相關實現http://man7.org/linux/man-pages/man2/open.2.html

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int
open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode); int creat(const char *pathname, mode_t mode); int openat(int dirfd, const char *pathname, int flags); int openat(int dirfd, const char *pathname, int flags, mode_t mode);

close()函式:

#include <unistd.h>

// 關閉一個開啟著的檔案,成功返回0,出錯返回-1
int close(int fd);

lseek()函式:

#include <unistd.h>

// 設定檔案偏移量,成功返回新的檔案偏移量,出錯返回-1
off_t lseek(int fd, off_t offset, int whence);
// fd為被設定的檔案的描述符,offset為偏移量(offset可正可負),whence決定從檔案哪個位置怎麼偏移

whence引數取值:
SEEK_SET: 將檔案偏移量設定為距檔案開始處offset個位元組
SEEK_CUR: 將檔案偏移量設定為當前偏移量加上offset
SEEK_END: 將檔案偏移量設定為檔案長度加上offset

注意:有的檔案允許當前偏移量為負值,因此在檢查lseek()執行是否成功時,應該檢查返回值
是否為-1,而不能檢查其是否小於零

read()、write()、pread()、pwrite()函式:

#include <unistd.h>

// 從檔案讀取資料和向檔案寫資料
// 成功則返回讀或寫的位元組數,出錯返回-1
ssize_t read(int fd, void *buf, size_t nbytes);
ssize_t write(int fd, const void *buf, size_t nbytes);

// 相當於先呼叫lseek()後再呼叫read()或write(),但相對於分開二個函式,此處函式操作是原子的
ssize_t pread(int fd, void *buf, size_t nbytes, off_t offset);
ssize_t pwrite(int fd, const void *buf, size_t nbytes, off_t offset);

dup()和dup2()函式:

#include <unistd.h>

// 複製一個現有的檔案描述符,若成功返回新的檔案描述符,出錯返回-1
int dup(int fd);
int dup2(int fd, int fd2);

相對於dup(),dup2()可以用fd2指定新的檔案描述符值
若果fd2已經開啟,則dup2()先將其關閉,當fd2等於fd,則返回fd2,而不關閉它
注意:不要把檔案描述符當做int,認為可以通過賦值語句賦值一個檔案描述符

檔案同步相關函式:

#include <unistd.h>

void sync(void);
// 成功返回0,出錯返回-1
int fsync(int fd);
int fdatasync(int fd);

在向檔案中寫入資料時,核心會先將資料複製到緩衝區,然後排入佇列,晚些時候在寫入磁碟(延遲寫)
在為了保證實際檔案系統與緩衝區中內容一致性時,我們使用上述的三個函式
sync()將所有修改過的塊緩衝區排入寫佇列,然後返回,並不等待實際的寫磁碟操作是否完成
fsync()同步時,只對fd指定的檔案有用,且等待實際寫磁碟操作結束才返回
fdatasync()與fsync()類似,但只更新檔案資料,而fsync()出資料外還更新檔案屬性

fcntl()函式:

#include <fcntl.h>

// 若成功,返回值由cmd引數決定,出錯返回-1
int fcntl(int fd, int cmd, ... /* arg */);


關於fcntl()函式的man文件中的描述:https://linux.die.net/man/2/fcntl
具體解釋(中文):https://www.cnblogs.com/xuyh/p/3273082.html

ioctl()函式:

#include <unistd.h>

int ioctl(int fd, int request, ... );