目录
1.打开文件
1.1 函数原型介绍
1.1.1 open函数
1.1.2 creat函数
1.1.2 openat函数
1.2 内核源码分析
1.3 函数原型区别
2.关闭文件
2.1 函数原型介绍
2.1.1 close函数
2.2 内核源码实现
#include
#include
#include
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
函数简介:open函数用于打开一个文件,并返回一个文件描述符,应用程序可以通过文件描述符对文件进行读写等操作。open函数可以打开已经存在的文件,也可以创建一个新文件。
函数参数:
pathname:是文件的路径名。
flags:打开文件时的标志,可以设置为以下值之一或多个值的按位或:
mode:只有在O_CREAT标志被设置时才有效,用于指定文件的访问权限,可以设置为以下值之一:
#define S_IRWXU 00700 //用户可读,可写,可执行
#define S_IRUSR 00400 //用户可读
#define S_IWUSR 00200 //用户可写
#define S_IXUSR 00100 //用户可执行
#define S_IRWXG 00070 //组可读,可写,可执行
#define S_IRGRP 00040 //组可读
#define S_IWGRP 00020 //组可写
#define S_IXGRP 00010 //组可执行
#define S_IRWXO 00007 //其他用户可读,可写,可执行
#define S_IROTH 00004 //其他用户可读
#define S_IWOTH 00002 //其他用户可写
#define S_IXOTH 00001 //其他用户可执行
mode可以通过八进制赋值,例如设置为0777,0777表示所有权限按位或。
需要注意的是mode需要与系统umask值共同作用才能得到最终的文件权限,umask作用去掉哪些权限,比如umask值为0022(八进制),标识去掉S_IWGRP和S_IWOTH权限。
文件最终权限计算方法为: mode &~ umask.
举例说明:
mode设置为0777,umask值为0022,文件最终权限为0755。
函数返回值:
成功:返回文件描述符,文件描述符为非负整数。
失败:返回-1,并设置errno。
示例代码
#define TEST_FILE "/tmp/test.txt"
int open_test() {
int fd = open(TEST_FILE, O_RDWR | O_CREAT | O_TRUNC, 0777);
if (fd == -1) {
perror("open error");
return -1;
}
return 0;
}
#include
#include
#include
int creat(const char *pathname, mode_t mode);
函数简介:creat函数用于创建并打开一个新文件,并返回一个文件描述符,如果文件已经存在,则会将其截断为0字节,应用程序可以通过文件描述符对文件进行读写等操作。
函数参数:
pathname:文件路径名。
mode:是新文件的权限(参考open函数)。
函数返回值:
成功:返回文件描述符,文件描述符为非负整数。
失败:返回-1,并设置errno。
示例代码:
int creat_test() {
int fd = creat(TEST_FILE, 0644);
if (fd == -1) {
perror("creat error");
return -1;
}
return 0;
}
#include
#include
#include
int openat(int dirfd, const char *pathname, int flags);
int openat(int dirfd, const char *pathname, int flags, mode_t mode);
函数简介:openat函数用于在指定目录下打开文件并返回文件描述符。它与open函数类似,但可以指定相对路径来打开文件,而不需要提供完整的文件路径。
函数参数:
dirfd:已打开的文件目录描述符。
pathname:是指定文件名的字符串。
flags:打开文件时的标志(参考open函数)。
mode:是新文件的权限(参考open函数)。
openat函数dirfd和pathname参数组合关系:
函数返回值:
成功:返回文件描述符,文件描述符为非负整数。
失败:返回-1,并设置errno。
示例代码:
#define DIR_PATH "/tmp"
#define FILE "test.txt"
int openat_test() {
int dirfd = open(DIR_PATH, O_RDONLY);
if (dirfd == -1) {
perror("open dir error");
return -1;
}
int fd = openat(dirfd, FILE, O_RDWR | O_CREAT | O_TRUNC, 0644);
if (fd == -1) {
perror("openat error");
return -1;
}
return 0;
}
图 1-1 open函数内核源码分析
open,creat,openat通过系统调用再调用一个共同的函数do_sys_open函数,do_sys_open函数有四个参数:dfd,path,flags,mode。这四个参数对应openat函数原型四个参数。
open函数没有dfd参数,所以在调用do_sys_open函数之前dfd设置为默认值AT_FDCWD(当前工作目录)。
creat函数没有dfd参数和flags参数,所以在调用do_sys_open函数之前dfd设置为默认值AT_FDCWD(当前工作目录),以及flags设置为默认值O_WRONLY | O_CREAT | O_TRUNC,creat因为flags默认值的关系,所以只能新建文件或者截断文件长度至0来打开文件。
openat函数需要传递四个参数至do_sys_open函数。
打开文件描述符系列函数源码调用路径如图,这里就不再赘述。
(1)open函数和creat函数区别
(2)open函数和openat函数区别
#include
int close(int fd);
函数简介:close函数的作用是关闭文件描述符并释放相关资源。
函数参数:
fd:表示需要关闭的文件描述符。
函数返回值:
成功:返回0.
失败:返回-1,并设置errno,一些常见的错误码包括:
图 2-1 close函数内核源码分析
close函数通过系统调用sys_close函数进入内核空间,close通过fd找到struct file对象并清除和释放该对象,struct file的f_op成员会根据文件系统和文件类型不一样而设置不同的值,关闭文件时,也会调用f_op对应的一些具体函数清除资源,典型的情况如socket关闭,socket关闭需要完成三次握手,需要通过f_op->release函数实现。