文件打開
用open或openat可打開或創建文件
#include <fcntl.h>
int open( const char *path, int flags,.../*mode_t mode*/);
int openat( int fd, const char *path, int flags,.../*mode_t mode*/);
參數:
- path:文件路徑(帶文件名)
- flag:打開選項
- 以下選項必須指定且只能指定一個
- O_RDONLY:只讀,一般爲0
- O_WRONLY:只寫,一般爲1
- O_RDWR:可讀寫,一般爲2
- O_EXEC:只執行打開
- O_SEARCH:只搜索打開(用於目錄)
- 以下常量可選
- O_APPEND:追加到文件末尾
- O_CREAT:文件不存在則創建,mode參數指定新文件訪問權限位
- O_DIRECTORY:若path引用的不是目錄,則出錯。
- O_EXCL:與O_CREAT合用,文件不存在則創建,存在則報錯,使得檢測與創建合併爲原子操作。
- O_NONBLOCK:若path引用的是fifo、塊特殊文件或字符特殊文件,則標誌着此次打開和後續IO操作都不阻塞。
- O_SYNC:使每次write等待物理IO完成。
- O_TRUNC:若文件存在且以只寫/讀寫方式打開,則將文件截斷爲0.
- O_DSYNC:使每次write等待物理IO完成,若寫不影響讀,則不等待文件屬性更新。
- ……
- 以下選項必須指定且只能指定一個
返回值:最小未用過的文件描述符的值;出錯返回 -1
open 與openat 區別
兩者區別在於fd的值,有3種情況:
- 若path是絕對路徑,則忽略fd,openat 等於open
- 若path是相對路徑,則fd指定了path的參照地址,fd引用的是打開的目錄
- path爲相對路徑,fd取特殊值AT_FDCWD,則path參照當前目錄,openat與open等同。
文件創建
create函數用於創建文件
#include<fcntl.h>
int creat(const char *path, mode_t mode);
等價於:
open(path, O_WRONLY|O_CREAT|O_TRUNC, mode)
返回值:文件描述符,出錯返回-1。
文件關閉
close 用於關閉文件
#include<unistd.h>
int close(int fd);
關閉文件會釋放該進程加在文件上的所有記錄鎖;
進程終止時,內核自動關閉它所打開的文件。
測試代碼:
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
int main()
{
printf("rdonly:%d wronly:%d rdwr:%d\n", O_RDONLY, O_WRONLY, O_RDWR); // 0 1 2
// 文件不存在
int fd = open("./filenoexist.txt", O_RDONLY);
if (fd < 0)
printf("open fail\n");
else
close(fd);
// 創建文件
//fd = open("./filenoexist.txt", O_CREAT, 0400); // 創建權限爲只讀,後面的寫嘗試都會失敗
fd = open("./filenoexist.txt", O_CREAT, 0600);
if (fd < 0)
printf("create fail\n");
else
printf("create success\n");
close(fd);
//再次創建,但是必須不存在
fd = open("./filenoexist.txt", O_CREAT | O_EXCL);
if (fd < 0)
printf("file already exists\n");
else
close(fd);
// 只讀打開,嘗試寫
fd = open("./filenoexist.txt", O_RDONLY);
char buf[64];
snprintf(buf, sizeof(buf), "hello world.");
//int ret = write(fd, buf, sizeof(buf)); // 可以看看用sizeof和strlen的區別
int ret = write(fd, buf, strlen(buf));
if (ret < 0)
printf("read only write fail.\n");
else
printf("read only write succ:%s.\n", buf);
close(fd);
// 只寫打開,嘗試讀
fd = open("./filenoexist.txt", O_WRONLY);
memset(buf, 0x0, sizeof(buf));
ret = read(fd, buf, sizeof(buf));
if (ret < 0)
printf("write only read fail.\n");
else
printf("write only read succ:%s.\n", buf);
close(fd);
// 讀寫打開,嘗試寫
fd = open("./filenoexist.txt", O_RDWR);
memset(buf, 0x0, sizeof(buf));
snprintf(buf, sizeof(buf), "hello world.");
ret = write(fd, buf, strlen(buf));
if (ret < 0)
printf("write fail.\n");
close(fd);
// 讀寫打開,嘗試讀
fd = open("./filenoexist.txt", O_RDWR);
char rdbuf[128];
memset(rdbuf, 0x0, sizeof(rdbuf));
ret = read(fd, rdbuf, sizeof(rdbuf));
if (ret < 0)
printf("read fail.\n");
else
printf("read succ:%s.\n", rdbuf);
close(fd);
// 追加文件
fd = open("./filenoexist.txt", O_WRONLY|O_APPEND);
memset(buf, 0x0, sizeof(buf));
snprintf(buf, sizeof(buf), "hello world.");
ret = write(fd, buf, strlen(buf));
if (ret < 0)
printf("append write fail.\n");
else
printf("append succ:%s.\n", buf);
close(fd);
// 讀寫打開,嘗試讀
fd = open("./filenoexist.txt", O_RDWR);
//char rdbuf[128];
memset(rdbuf, 0x0, sizeof(rdbuf));
ret = read(fd, rdbuf, sizeof(rdbuf));
if (ret < 0)
printf("read fail.\n");
else
printf("read succ:%s.\n", rdbuf);
close(fd);
// 截斷打開
fd = open("./filenoexist.txt", O_WRONLY|O_TRUNC);
memset(buf, 0x0, sizeof(buf));
snprintf(buf, sizeof(buf), "talk is cheap.");
ret = write(fd, buf, strlen(buf));
if (ret < 0)
printf("write fail.\n");
close(fd);
}
編譯運行,結果:
rdonly:0 wronly:1 rdwr:2
create success
file already exists
read only write fail.
write only read fail.
read succ:hello world.p..
append succ:hello world..
read succ:hello world.p.hello world..
最後一行hello world 之間的p,是因爲代碼中“talk is cheap” 末尾的p,“hello world”沒有覆蓋完,留下的~
編程學習要通過實踐才能進步,即使照着書上代碼抄,也得嘗試修改,看看輸出結果和預想的是否相同,不同是什麼原因。
參考:
《Unix環境高級編程》3.3-3.5 小節