Linux 文件IO学习之open函数深入了解

article/2025/10/23 14:53:18

open()函数是在学习文件IO中的第一个函数。作用是打开一个文件,或者创建出一个文件。

需要注意的是,能实现这样功能的函数其实有两套,一个是系统IO所提供的open()函数,一个是标准IO提供的fopen()函数。(二者对比放在最后)

先看看open函数定义:

       int open(const char *pathname, int flags);
       int open(const char *pathname, int flags, mode_t mode);

        // 系统IO提供的函数接口

 注:Linux下man手册使用在前面文章中有详细讲解,可通过往期文章查看学习。

参数解析:

pathname:英文直译是路径名称的意思。

数据类型为 const char* 可以填写字符串的字面常量(指直接用 " " 引起来的字符串),这个路径可以填绝对路径和名称。直接填名称会自动检索当前目录下的文件。

flags:标志(本质上是一个数字)

O_RDONLY 以只读方式打开文件
O_WRONLY 以只写方式打开文件
O_RDWR 以可读写方式打开文件.
// 上述三种旗标是互斥的, 也就是不可同时使用,
// 但可与下列的旗标利用 OR(|)运算符组合.
O_CREAT 若欲打开的文件不存在则自动建立该文件.
O_EXCL 如果 O_CREAT 也被设置, 此指令会去检查文件是否存在. 文件若不存在则建立该文件, 否
O_NOCTTY 如果欲打开的文件为终端机设备时, 则不会将该终端机当成进程控制终端机.
O_TRUNC 若文件存在并且以可写的方式打开时, 此旗标会令文件长度清为 0, 而原来存于该文件的资
O_APPEND 当读写文件时会从文件尾开始移动, 也就是所写入的数据会以附加的方式加入到文件后面
O_NONBLOCK 以不可阻断的方式打开文件, 也就是无论有无数据读取或等待, 都会立即返回进程之中
O_NDELAY 同 O_NONBLOCK.
O_SYNC 以同步的方式打开文件.
O_NOFOLLOW 如果参数 pathname 所指的文件为一符号连接, 则会令打开文件失败.

要点:

1.O_RDONLY,O_WRONLY,O_RDWR三个互斥:

 

不可以同时使用,也不能添加 | (本质上都占用了两个同样的数字位),其余的旗标是可以加 | 的(占用不同的数字位)。

例如:8bit控制位,控制读写的在第1,2bit,xxxxxx00表示读数据,xxxxxx01表示写数据,xxxxxx11表示读写。这时O_RDONLY | O_WRONLY (00 | 01)还是只能得到数字01(O_WRONLY),对这三个旗标用 | 进行操作意义不大。

 

 

2. O_CREAT | O_EXCL 常用组合作用解析。

调用 open("abc.c",O_CREAT|O_EXCL);

系统会自动检测当前路径下"abc.c"文件是否存在。

如果存在,就返回 -1 (文件打开错误)。

如果不存在,就自动创建文件并返回文件当前进程ID。

代码验证:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
int main()
{char file_name[128] = "abc.c";int fd = open(file_name,O_EXCL|O_CREAT);if(fd == -1){printf("open %s fail!",file_name);return -1;}else{printf("open %s success!",file_name);}
}

代码编译后运行结果如下: 

e9897df4ed0a448ba4523264abe83cb9.png

 第一次运行前,目录下不存在  “abc.c”   目标文件,程序创建(O_CREAT)并打开成功。

第二次运行时,目录下存在  “abc.c”  目标文件,程序检测(O_EXCL)并返回-1报错。

 

3.O_TRUNC 与 O_APPEND

写入文件时,系统默认将光标移动到文件开头。

O_TRUNC:作用是在光标移动的同时将文件长度清零(清空文件)。

O_APPEND:作用是在尾部追加内容,即将光标移动到文件末尾。

代码验证:

//文件成功打开后提示打开成功并且向文件写入“12”
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
int main()
{char file_name[128] = "abc.c";int fd = open(file_name,O_RDWR);if(fd == -1){printf("open %s fail!\n",file_name);return -1;}else{printf("open %s success!\n",file_name);write(fd,"12",sizeof("12"));}
}

开始时文件内容如下:

e36f9d3260d04618b33150f1d48f6d87.png

调用 open(file_name,O_RDWR)并写入"12"结果如下:

f0ac6c7b32e44bbdb8abee9f82a688b6.png

注:这里是系统默认将光标移动到开头并且写入,没有清除后面文件内容。

 

调用 open(file_name,O_RDWR | O_TRUNC)并写入"12"结果如下:

1a73b60f015848eab80c00b53e86bf36.png

 注:这里打开的时候,将光标移动到开头的同时将文件内容清零。

调用 open(file_name,O_RDWR | O_APPEND)并写入"12"结果如下:

f8308962bf0d4b74acfb7648af251422.png

  注:这里打开的时候,将光标移动到末尾进行写入,不破坏原来文件的内容。

 

4.O_NONBLOCK解析

在文件处于阻塞状态时强行打开文件。

例如我写了个只有从串口接收到数据才能关闭并且保存文件的程序,如果程序迟迟没有从串口中接收到数据,那么文件就会一直处于阻塞状态中等待数据,这个时候文件无法正常打开,需要添加此旗标。

暂无代码验证...

 

其他参数讲解:

在man函数查询到的open定义中。

除了    int open(const char *pathname, int flags);之外,还有一个比较特殊的函数定义。

 int open(const char *pathname, int flags, mode_t mode);

这个函数和上面的对比,返回值和前两个参数都是一样的。

这里解释一下第三个参数mode:

这个函数的作用在于在创建文件的时候设定文件的初始权限。mode_t类型是一个12bit类型数据。 

对此参数,官方设定了一些宏定义:

 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 权限, 代表其他用户具有可执行的权限.

我们也可以自己写入一些参数定义它的用户权限(部分运行环境可能不行)。

 需要注意的是,对于设置文件权限,并不是“写入多少就是多少”,设置权限的时候,还受到umask掩码的影响。

umask对于文件的影响:

文件最终权限 = 写入权限 - umask

代码验证:

char file_name[128] = "test";
open(file_name,O_RDWR|O_CREAT,0727);

按以上函数创建一个文件。

此时我的umask值是 007

 0c8f08f0c9bc42969777425c93511621.png

这时候创建文件,其权限为:

5473869b3bc544ddabee5aa3d1da648b.png=

注意看,umask的值为007,对应test权限的低3位,这时它的低3位权限是被屏蔽掉的,哪怕我设置的初始权限为0727.

现在将我的umask值改为070:

996294dc55a740f68a3ed469f0c7dbd1.png

这个时候再次以0727的权限创建文件,创建后结果如下:

693b86c7408a4915955a7aaaf543296a.png

此时低3位得到设置,但是中间三位就被屏蔽了。

 

函数返回值解释 :

open()函数的返回值是一个int,返回的是当前进程的进程ID。

注:这个ID只是当前进程下的ID。

 

对于返回值,我们可以对比一下 标准IO:

对于系统IO和标准IO的不同,上篇文章有提到过:

系统IO提供的接口功能单一,并且没有设置缓冲区。

而标准IO功能更加多样化,并且是带有缓冲区的。

 

 

而标准IO下的fopen()函数定义是这样的:

FILE *fopen(const char *pathname, const char *mode);

对比open():

 int open(const char *pathname, int flags);

输入参数大同小异,最大的区别在于返回值。

fopen返回的是一个结构体指针,结构体指针指向FILE结构体会包含除了进程ID以外更多的文件信息。调用时也会自动开辟缓冲区,读取信息后在调用open()函数操作。 

 

相较而言,open函数会比fopen()函数更加“底层”一些。

 

 


http://chatgpt.dhexx.cn/article/WT03L295.shtml

相关文章

Python open函数详解

演示环境&#xff0c;操作系统&#xff1a;Win10 21H2&#xff08;64bit&#xff09;&#xff1b;Python解释器&#xff1a;3.8.10。 open是Python的一个内置函数&#xff0c;一般用于本地文件的读写操作。用法如下。 my_file open(file, mode, buffering, encoding, errors…

sql去重查询

背景&#xff1a; 项目有消息推送&#xff0c;根据消息推送记录&#xff0c;筛选出一共有哪几种消息类型&#xff0c;并且标题和文本是什么 表部分结构如图&#xff1a; 主要是根据subject来去重所有数据&#xff0c;难点是&#xff0c;使用distinct的话&#xff0c;无法显示…

sql 去重查询 distinct

sql 去重查询 select Distinct UserId,Name from UserInfo where UserType1 介绍 distinct一般是用来去除查询结果中的重复记录的&#xff0c;而且这个语句在select、insert、delete和update中只可以在select中使用&#xff0c; 具体的语法如下&#xff1a; select distinc…

SQL去重的三种方法

目录 1.distinct去重 2.group by去重 3.row_number() over (parttion by 分组列 order by 排序列) 有这么一张test的表, 我们将对这张表进行操作来自验证去重 这里的去重&#xff1a;查询的时候, 不显示重复&#xff0c;并不是删除表中的重复项 1.distinct去重 只能一列去…

SQL去重方法汇总

更多教程请到友情连接&#xff1a; 菜鸟教程https://www.piaodoo.com 茂名一技http://www.enechn.com ppt制作教程步骤 http://www.tpyjn.cn 兴化论坛http://www.yimoge.cn 电白论坛 http://www.fcdzs.com 在使用SQL提数的时候&#xff0c;常会遇到表内有重复值的时候&…

SQL中去除重复数据的几种方法,我一次性都告诉你​

使用SQL对数据进行提取和分析时&#xff0c;我们经常会遇到数据重复的场景&#xff0c;需要我们对数据进行去重后分析。 以某电商公司的销售报表为例&#xff0c;常见的去重方法我们用到distinct 或者group by 语句&#xff0c; 今天介绍一种新的方法&#xff0c;利用窗口函数对…

SQL:数据去重的三种方法

1、使用distinct去重 distinct用来查询不重复记录的条数&#xff0c;用count(distinct id)来返回不重复字段的条数。用法注意&#xff1a; distinct【查询字段】&#xff0c;必须放在要查询字段的开头&#xff0c;即放在第一个参数&#xff1b;只能在SELECT 语句中使用&#…

SQL去重的三种方法汇总​

SQL去重的三种方法汇总​ 这里的去重是指&#xff1a;查询的时候, 不显示重复&#xff0c;并不是删除表中的重复项 1.distinct去重 注意的点&#xff1a;distinct 只能一列去重&#xff0c;当distinct后跟大于1个参数时&#xff0c;他们之间的关系是&&(逻辑与)关系&a…

SQL去重

SQL去重是数据分析工作中比较常见的一个场景&#xff0c;今天给大家具体介绍3种去重的方法。在使用SQL提数的时候&#xff0c;常会遇到表内有重复值的时候&#xff0c;比如我们想得到 uv &#xff08;独立访客&#xff09;&#xff0c;就需要做去重。 在 MySQL 中通常是使用 di…

SQL查询去掉重复数据

本文主要总结数据库去掉重复数据的方法 去掉重复数据的方法&#xff1a; 第一种&#xff1a;distinct 根据单个字段去重&#xff0c;能精确去重&#xff1b;作用在多个字段时&#xff0c;只有当这几个字段的完全相同时&#xff0c;才能去重&#xff1b;关键字distinct只能放…

大数据系统基础 | 绪论

1 什么是大数据 1、Big data is an all-encompassing term for any collection of data sets so large and complex that it becomes difficult to process using traditional data processing apllications. -http://en.wikipedia.org/wiki/Big_data 2、如果一个数据集的规…

大数据测试

目录 1、前言 2、大数据测试策略 3、如何测试大数据应用程序 4、架构测试 5、性能测试 6、性能测试方法 7、性能测试参数 8、测试环境需求 9、大数据测试对比传统数据库测试 10、大数据场景中使用的工具 11、大数据测试的挑战 12、性能测试挑战 1、前言 大数据…

大数据系统测评服务

1. 专业服务 围绕大数据的基础平台、分析软件产品、大数据应用系统、大数据交易系统等&#xff0c;面向政府主管机构、大数据解决方案提供商和大数据建设需求方等提供支撑、测试和咨询服务。测试报告可作为大数据产品或系统市场推广或验收提供客观依据。 大数据基础平台测试…

大数据系统发展的技术路线

自从大数据出来后&#xff0c;数据管理界发生了巨大的变化&#xff0c;技术驱动成为大数据管理系统的一个主要变革力量。 传统的数据库管理系统以结构化数据为主&#xff0c;因此关系数据库系统&#xff08;RDBMS&#xff09;可以一统天下满足各类应用需求。然而&#xff0c;大…

大数据平台开发:大数据系统架构模块解析

企业要开展大数据相关业务&#xff0c;首先就需要基于自身的需求&#xff0c;来设计搭建数据系统平台。而大数据系统平台的搭建&#xff0c;需要基于实际需求&#xff0c;来进行系统架构规划。今天我们就从大数据平台开发的角度&#xff0c;来对大数据系统架构模块做一个简单的…

大数据画像系统-1.0

大数据画像系统-1.0 写在最前面操作流程与资源资源获取创建 Flask 工程添加必要第三方库将刚刚下载的文件放入 Flask 工程运行 效果首页城市数据页个人画像页 结语 写在最前面 你能找到这篇文章&#xff0c;那么画像系统是什么&#xff0c;你应该已经知道&#xff0c;大数据是…

【云计算与大数据技术】大数据系统总体架构概述(Hadoop+MapReduce )

一、总体架构设计原则 企业级大数据应用框架需要满足业务的需求&#xff0c;一是要求能够满足基于数据容量大&#xff0c;数据类型多&#xff0c;数据流通快的大数据基本处理需求&#xff0c;能够支持大数据的采集&#xff0c;存储&#xff0c;处理和分析&#xff0c;二是要能…

大数据系统计算技术展望

大数据是新一代信息技术的核心方面和竞争前沿&#xff0c;也是制约大数据产业快速发展的关键瓶颈。大数据技术创新能力已经成为后信息时代衡量国家竞争力的重要指标。与传统信息产业的发展过程相似&#xff0c;大数据必将逐渐形成一个相对独立、体系完善的产业形态&#xff0c;…

什么是大数据系统架构

大数据的应用开发过于偏向底层&#xff0c;具有学习难度大&#xff0c;涉及技术面广的问题&#xff0c;这制约了大数据的普及。现在需要一种技术&#xff0c;把大数据开发中一些通用的&#xff0c;重复使用的基础代码、算法封装为类库&#xff0c;降低大数据的学习门槛&#xf…

大数据系统的基础,大数据存储和计算技术

在存储方面&#xff0c;2000 年左右谷歌等提出的文件系统(GFS)、以及随后的 Hadoop 的分布式文件系统 HDFS(Hadoop Distributed File System)奠定了大数据存储技术的基础。 与传统系统相比&#xff0c;GFS/HDFS 将计算和存储节点在物理上结合在一起&#xff0c;从而避免在数据…