文件IO_打开和关闭文件(附Linux-5.15.10内核源码分析)

目录

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 内核源码实现


1.打开文件

1.1 函数原型介绍

1.1.1 open函数

#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);

函数简介:open函数用于打开一个文件,并返回一个文件描述符,应用程序可以通过文件描述符对文件进行读写等操作。open函数可以打开已经存在的文件,也可以创建一个新文件。

函数参数:

pathname:是文件的路径名。

flags:打开文件时的标志,可以设置为以下值之一或多个值的按位或:

  • O_RDONLY:只读打开
  • O_WRONLY:只写打开
  • O_RDWR:读写打开
  • O_CREAT:如果文件不存在,则创建文件
  • O_TRUNC:如果文件存在且以写方式打开,则截断文件为零长度
  • O_APPEND:以追加方式打开文件

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;
}

1.1.2 creat函数

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>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;
}

1.1.2 openat函数

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>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:pathname为绝对路径时,按绝对路径方式打开文件,dirfd失效。
  • 组合2:pathname为相对路径时,由dirfd(文件目录)和pathname(相对路径)共同决定打开的文件名。
  • 组合3:pathname为相对路径时,如果dirfd设置为AT_FDCWD(当前工作目录),由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.2 内核源码分析

图 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.3 函数原型区别

 (1)open函数和creat函数区别

  • 区别1:open函数可以打开已存在的文件,也可以创建新文件,而creat函数只能创建新文件。如果文件已存在,creat函数会将其截断为零长度。
  • 区别2:open函数的标志参数可以更加灵活地指定文件的打开方式,包括只读、只写、读写、追加等选项。而creat函数只能以写方式打开文件,并且具有固定的标志(O_WRONLY | O_CREAT | O_TRUNC)。

(2)open函数和openat函数区别

  • 区别1:open函数接受一个文件路径名作为参数,该路径名可以是绝对路径或相对路径。 openat函数需要传递一个已打开的目录文件描述符(dirfd)和一个相对于该目录的路径名作为参数。这种方式可以更加灵活地控制文件的打开位置。
  • 区别2:目录解析方式: open函数的文件路径名会根据当前进程的工作目录进行解析。 openat函数的路径名是相对于提供的目录文件描述符(dirfd)进行解析。
  • 区别3:安全性考虑: open函数在解析文件路径时,依赖于进程的当前工作目录。这可能会导致安全性问题,特别是在多线程环境下,因为当前工作目录是共享的。 openat函数提供了更安全的方式,可以避免依赖于进程的当前工作目录,而是通过提供目录文件描述符来指定相对路径。

2.关闭文件

2.1 函数原型介绍

2.1.1 close函数

#include <unistd.h>int close(int fd);

函数简介:close函数的作用是关闭文件描述符并释放相关资源。

函数参数:

fd:表示需要关闭的文件描述符。

函数返回值:

成功:返回0.

失败:返回-1,并设置errno,一些常见的错误码包括:

  • EBADF:无效的文件描述符,即文件描述符未打开或已经关闭。
  • EINTR:操作被信号中断。
  • EIO:I/O错误。

2.2 内核源码实现

图 2-1 close函数内核源码分析

 close函数通过系统调用sys_close函数进入内核空间,close通过fd找到struct file对象并清除和释放该对象,struct file的f_op成员会根据文件系统和文件类型不一样而设置不同的值,关闭文件时,也会调用f_op对应的一些具体函数清除资源,典型的情况如socket关闭,socket关闭需要完成三次握手,需要通过f_op->release函数实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/22327.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

国产MCU-CW32F030开发学习-BH1750模块

国产MCU-CW32F030开发学习-BH1750模块 硬件平台 CW32_48F大学计划板CW32_IOT_EVA物联网开发评估套件BH1750数字型光照强度传感器 BH1750 BH1750是一款数字型光照强度传感器&#xff0c;能够获取周围环境的光照强度。其测量范围在0~65535 lx。lx勒克斯&#xff0c;是光照强…

前端漏洞xss

网络钓鱼、获取Cookie、强制弹窗获取流量、网站挂马(将恶意代码嵌入程序&#xff0c;用户浏览页面时计算机将被嵌入木马)、发送垃圾信息或广告、传播蠕虫病毒 漏洞原理 XSS(Cross Site Scripting),是一种跨站的脚本攻击&#xff0c;曾简称为CSS&#xff0c; 后改为XSS。 攻击…

git下载源码及环境搭建之数据库(二)

学习目标&#xff1a; 数据库 新项目使用 数据库文件 的配置 及相关属性的设置 步骤&#xff1a; 数据库 下图所示为开发时所用数据库 第一步&#xff1a;新建一个数据库 注意&#xff1a; 字符集与排序规则我们应该选择utf-8 相关 选中新创建的表&#xff0c;点击备份—还…

备战秋招009(20230714)

文章目录 前言一、Java内存区域1、JVM组成部分2、运行时数据区域01、基础02、程序计数器03、虚拟机栈04、本地方法栈05、堆06、方法区07、直接内存 3、HotSpot虚拟机对象01、对象的创建02、内存分配03、内存布局04、访问定位 二、垃圾回收1、堆空间01、空间结构02、GC 分类03、…

Unified Named Entity Recognition as Word-Word Relation Classification

原文链接&#xff1a;https://arxiv.org/pdf/2112.10070.pdf AAAI 2022 介绍 NER主要包括三种类型&#xff1a;flat、overlap和discontinuous。目前效果最好的模型主要是&#xff1a;span-based和seq2seq&#xff0c;但前者注重于边界的识别&#xff0c;后者可能存在exposure b…

OpenCV 入门教程:自适应阈值处理

OpenCV 入门教程&#xff1a;自适应阈值处理 导语一、自适应阈值处理二、示例应用2.1 图像二值化2.2 图像去噪 总结 导语 自适应阈值处理是图像处理中常用的技术之一&#xff0c;它能够根据图像的局部特征自动调整阈值&#xff0c;从而提高图像的处理效果。在 OpenCV 中&#…

LabVIEW-实现波形发生器

一、题目 用两种方法实现一种多类型信号波形发生器&#xff08;至少包括&#xff1a;正弦波、三角波、方波等&#xff09;&#xff0c;可以调节信号频率、幅度、相位等参数&#xff0c;可以图形化显示信号波形。 需要给出产生信号波形的基本方法、程序设计基本方法以及程序实现…

SpringCloud(4) Eureka 如何主动下线服务节点

目录 1.直接停掉客户端服务2.发送HTTP请求1&#xff09;调用DELETE接口2&#xff09;调用状态变更接口 3.客户端主动通知注册中心下线1&#xff09;代码示例2&#xff09;补充3&#xff09;测试 一共有三种从 Eureka 注册中心剔除服务的方式&#xff1a; 1.直接停掉客户端服务…

慢速减压控制技术在预防同步辐射光源和原位透射电镜氮化硅窗口膜真空中破裂的应用

摘要&#xff1a;氮化硅薄膜窗口广泛应用于同步辐射光源中的扫描透射软X射线显微镜和原位透射电镜&#xff0c;但氮化硅薄膜只有几百纳米的厚度&#xff0c;很容易因真空抽取初期的快速压差变化造成破裂。为此&#xff0c;本文提出了线性缓变压力控制解决方案&#xff0c;即控制…

物业小程序制作:提升管理效率与服务质量

随着物业管理的日益复杂&#xff0c;物业小程序成为了提高管理效率和提供优质服务的重要工具。物业小程序旨在提供高效的物业管理服务。通过物业小程序&#xff0c;物业公司能够方便地与业主进行信息交流、报修处理等操作。 物业小程序的好处 提高管理效率&#xff1a;物业小程…

七大排序算法——堆排序,通俗易懂的思路讲解与图解(完整Java代码)

文章目录 一、排序的概念排序的概念排序的稳定性七大排序算法 二、堆排序核心思想代码实现 三、性能分析四、七大排序算法 一、排序的概念 排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递…

【微信小程序-uniapp】CustomPickerMul 自定义多选选择器组件

1. 效果图 2. 组件完整代码 <template><view class="custom-picker-mul"><view :class&#