c/c++文件操作學習
open函數
函數
int open(const char * pathname, int flags);
int open(const char * pathname, int flags, mode_t mode);
pathname:指路徑
flag | 功能 |
---|---|
O_RDONLY | 以只讀方式打開文件 |
O_WRONLY | 以只寫方式打開文件 |
O_RDWR | 以可讀寫方式打開文件 |
上述三種旗標是互斥的, 也就是不可同時使用, 但可與下列的旗標利用OR運算符組合 | |
O_CREAT | 若欲打開的文件不存在則自動建立該文件 |
O_EXCL | 如果O_CREAT 也被設置, 此指令會去檢查文件是否存在. 文件若不存在則建立該文件, 否則將導致打開文件錯誤. 此外, 若O_CREAT 與O_EXCL 同時設置, 並且欲打開的文件爲符號連接, 則會打開文件失敗 |
O_NOCTTY | 如果欲打開的文件爲終端機設備時, 則不會將該終端機當成進程控制終端機 |
O_TRUNC | 若文件存在並且以可寫的方式打開時, 此旗標會令文件長度清爲0, 而原來存於該文件的資料也會消失 |
O_APPEND | 當讀寫文件時會從文件尾開始移動, 也就是所寫入的數據會以附加的方式加入到文件後面 |
O_NONBLOCK | 以不可阻斷的方式打開文件, 也就是無論有無數據讀取或等待, 都會立即返回進程之中 |
O_NDELAY | 同O_NONBLOCK |
O_SYNC | 以同步的方式打開文件 |
O_NOFOLLOW | 如果參數pathname |
O_DIRECTORY | 如果參數pathname 所指的文件並非爲一目錄, 則會令打開文件失敗 |
參數mode 則有下列數種組合, 只有在建立新文件時纔會生效, 此外真正建文件時的權限會受到umask 值所影響, 因此該文件權限應該爲 (mode-umaks)
mode | 權限 |
---|---|
S_IRWXU00700 | 代表該文件所有者具有可讀、可寫及可執行的權限 |
S_IRUSR 或S_IREAD, 00400 | 代表該文件所有者具有可讀取的權限 |
S_IWUSR 或S_IWRITE, 00200 | 代表該文件所有者具有可寫入的權限 |
S_IXUSR 或S_IEXEC, 00100 | 代表該文件所有者具有可執行的權限 |
S_IRWXG 00070 | 代表該文件用戶組具有可讀、可寫及可執行的權限 |
S_IRGRP 00040 | 代表該文件用戶組具有可讀的權限 |
S_IWGRP 00020 | 代表該文件用戶組具有可寫入的權限 |
S_IXGRP 00010 | 代表該文件用戶組具有可執行的權限 |
S_IRWXO 00007 | 代表其他用戶具有可讀、可寫及可執行的權限 |
S_IROTH 00004 | 代表其他用戶具有可讀的權限 |
S_IWOTH 00002 | 代表其他用戶具有可寫入的權限 |
S_IXOTH 00001 | 代表其他用戶具有可執行的權限 |
錯誤代碼
參數 | 功能 |
---|---|
EEXIST | 參數pathname 所指的文件已存在, 卻使用了O_CREAT 和O_EXCL 旗標 |
EACCESS | 參數pathname 所指的文件不符合所要求測試的權限 |
EROFS | 欲測試寫入權限的文件存在於只讀文件系統內 |
EFAULT | 參數pathname 指針超出可存取內存空間 |
EINVAL | 參數mode 不正確 |
ENAMETOOLONG | 參數 pathname 太長 |
ENOTDIR | 參數pathname 不是目錄 |
ENOMEM | 核心內存不足 |
ELOOP | 參數pathname 有過多符號連接問題 |
EIO | I/O 存取錯誤 |
mmap函數
頭文件
#include <unistd.h>
#include <sys/mman.h>
函數
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offsize);
//mmap()用來將某個文件內容映射到內存中,對該內存區域的存取即是直接對該文件內容的讀寫。
參數說明
參數 | 說明 |
---|---|
start | 指向欲對應的內存起始地址,通常設爲NULL,代表讓系統自動選定地址,對應成功後該地址會返回 |
length | 代表將文件中多大的部分對應到內存 |
prot | 代表映射區域的保護方式,有下列組合 PROT_EXEC:映射區域可被執行 PROT_READ :映射區域可被讀取PROT_WRITE:映射區域可被寫入PROT_NONE:映射區域不能存取 |
flags | 會影響映射區域的各種特性:**MAP_FIXED **: 如果參數 start 所指的地址無法成功建立映射時,則放棄映射,不對地址做修正。通常不鼓勵用此旗標。**MAP_SHARED **: 對應射區域的寫入數據會複製迴文件內,而且允許其他映射該文件的進程共享。MAP_PRIVATE: 對應射區域的寫入操作會產生一個映射文件的複製,即私人的"寫入時複製" (copy on write)對此區域作的任何修改都不會寫回原來的文件內容。MAP_ANONYMOUS : 建立匿名映射,此時會忽略參數fd,不涉及文件,而且映射區域無法和其他進程共享。**MAP_DENYWRITE ** :只允許對應射區域的寫入操作,其他對文件直接寫入的操作將會被絕。MAP_LOCKED: 將映射區域鎖定住,這表示該區域不會被置換(swap)。在調用mmap()時必須要指定MAP_SHARED 或MAP_PRIVATE。 |
fd | open()返回的文件描述詞,代表欲映射到內存的文件 |
offset | 文件映射的偏移量,通常設置爲0,代表從文件最前方開始對應,offset必須是分頁大小的整數倍 |
返回值
若映射成功則返回映射區的內存起始地址,否則返回MAP_FAILED(-1),錯誤原因存於errno 中。返回值:若映射成功則返回映射區的內存起始地址,否則返回MAP_FAILED(-1),錯誤原因存於errno 中。
錯誤代碼:
代碼 | 功能 |
---|---|
EBADF | 參數fd 不是有效的文件描述詞 |
EACCES | 存取權限有誤。如果是MAP_PRIVATE 情況下文件必須可讀,使用MAP_SHARED 則要有PROT_WRITE 以及該文件要能寫入 |
EINVAL | 參數start、length 或offset 有一個不合法 |
EAGAIN | 文件被鎖住,或是有太多內存被鎖住 |
ENOMEM | 內存不足 |
使用中的問題
include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/mman.h> #include <iostream> using namespace std; int main()
{
int fd;
fd = open("Wandering.txt", O_RDWR | O_CREAT, 00777);
char* Out = (char*) mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
string He = "Hello World!";
char* str = (char*)&He;
cout << &He << endl;
Out[1] = '1';
while(*str != '\0')
{
cout << *str++ << endl;
}
munmap(Out, 100); /* 解除映射 */ }
當向mmap地址中寫入數據總是出現Bus error的提示
發生錯誤的原因是因爲mmap不能去擴展一個內容爲空的新文件,因爲大小爲0,所有本沒有與之對應的合法的物理頁,不能擴展。所以只需要在新創建的空文件中先寫入一些數據即可。
lseek()函數
所有打開的文件都有一個當前文件偏移量(current file offset),以下簡稱爲 cfo。cfo 通常是一個非負整數,用於表明文件開始處到文件當前位置的字節數。讀寫操作通常開始於 cfo,並且使 cfo 增大,增量爲讀寫的字節數。文件被打開時,cfo 會被初始化爲 0,除非使用了O_APPEND 。
函數調用
#include <unistd.h>
#include <sys/types.h>
off_t lseek(int filedes, off_t offset, int whence);
參數說明
返回值:
- -1:失敗
- 數據 新的偏移量
whence | 功能 |
---|---|
SEEK_SET | 文件偏移量將被設置爲 offset |
SEEK_CUR | 文件偏移量將被設置爲 cfo 加上 offset |
SEEK_END | 文件偏移量將被設置爲文件長度加上 offset |
SEEK_SET、SEEK_CUR 和 SEEK_END 是 System V 引入的,在這之前使用的是 0、1 和 2。