1. 程式人生 > >文件I/O相關函數

文件I/O相關函數

結束 nis close 解釋 cmd 數據復制 name 我們 htm

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, ... );

文件I/O相關函數