文件打开
用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 小节