当前位置: 首页 > news >正文

【Linux】文件周边001之系统文件IO

👀樊梓慕:个人主页

 🎥个人专栏:《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C++》《Linux》《算法》

🌝每一个不曾起舞的日子,都是对生命的辜负


目录

前言

1.C语言文件IO

1.1C语言文件IO接口汇总 

1.2当前路径指的是什么?

 1.3stdin、stdout、stderr

2.系统文件IO

2.1open

参数const char* pathname

参数int flags

*位图方式传参

参数mode_t mode

返回值int fd『 简要理解文件描述符』

2.2close

2.3write 

2.4read


前言

进程周边的相关内容暂时告一段落,下面我们开始学习文件部分。

学习『 系统文件IO』之前,我会与大家先复习一下C语言部分文件IO的相关接口,为后面的学习作『 铺垫』。系统文件IO部分,本篇文章会讲解『 基本的系统调用』:open()、close()、read()、write(),有关参数传递涉及到『 位图方式传递』,这部分以前没有学习过,博主也会拿出来简单的学习一下。


欢迎大家📂收藏📂以便未来做题时可以快速找到思路,巧妙的方法可以事半功倍。

=========================================================================

GITEE相关代码:🌟fanfei_c的仓库🌟

=========================================================================


1.C语言文件IO

1.1C语言文件IO接口汇总 

在学习C语言期间,我们学习过一些C语言封装的文件接口:

C语言文件接口汇总
打开文件
关闭文件
写入一个字符
读取一个字符
写入一个字符串
读取一个字符串
格式化写入数据
格式化读取数据
向二进制文件写入数据
从二进制文件读取数据
设置文件指针的位置
计算当前文件指针相对于起始位置的偏移量
设置文件指针到文件的起始位置
判断文件操作过程中是否发生错误
判断文件指针是否读取到文件末尾

本篇文章不会完全的讲解以上C语言文件接口,想要详细了解的同学可以『 点击以下内容』跳转到博主的有关C语言文件IO的博客。

『 樊梓慕』文件操作——CSDNicon-default.png?t=N7T8http://t.csdnimg.cn/DRPJb

1.2当前路径指的是什么?

当我们利用C语言IO接口创建文件时,生成的文件默认在『 当前路径』,可当前路径具体指的是谁的路径呢?

  • 『 文件是由进程创建』,所以文件的当前路径也是进程的当前路径。

在之前学习进程的部分,我们已经聊过有关话题,当前路径指的是进程在启动时,会保存当前目录的路径,保存到『 /proc/[pid]/cwd』中,该路径就是进程的当前路径。


 1.3stdin、stdout、stderr

在之前学习时,我们提到过一个概念:『 Linux下一切皆文件』 ,也就是说键盘、显示器都是文件,这很好理解,我们向普通文件写入,本质上就是向磁盘写入数据,那将对象改为显示器,是不是就是打印了?

但是,向文件写入我们一般这么操作:

FILE* fp = fopen("log.txt", "w");
fputs("hello world\n", fp);

可是打印我们从未『 打开』显示器文件,也从未『 传递』过流参数:

printf("hello world\n");

这也就说明了:

进程在运行的时候都会『 默认打开』三个输入输出流,即标准输入流、标准输出流以及标准错误流,对应到C语言当中就是stdin、stdout以及stderr。

其中,标准输入流对应的设备就是键盘,标准输出流和标准错误流对应的设备都是显示器。

所以,我们想要实现打印的功能,也可以这样写:

fputs("hello world\n", stdout);

stdin、stdout以及stderr是C标准库下的标准输入输出错误流,其他语言如C++也有对应的标准输入输出错误流:cin、cout和cerr。


2.系统文件IO

 C程序可以直接对硬件进行写入么?

在之前学习的时候,关于操作系统我们有过这样一张图:

什么意思?

程序不可能也不可以越过操作系统直接操作硬件,还记得『 系统调用』么?

 也就是说C标准库中的文件IO接口一定『 封装了系统调用』,所以才能利用fopen()、fputs()等函数对文件进行操作。

那接下来我们就来学习文件IO的系统调用。

2.1open

 open是打开文件的系统调用接口。

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

参数const char* pathname

代表要打开或创建的目标文件。 

  • 若pathname以路径的方式给出,则当需要创建该文件时,就在pathname路径下进行创建。
  • 若pathname以文件名的方式给出,则当需要创建该文件时,默认在当前路径下进行创建。

参数int flags

代表文件的打开方式。

参数含义
O_RDONLY以只读的方式打开文件
O_WRNOLY以只写的方式打开文件
O_APPEND以追加的方式打开文件
O_RDWR以读写的方式打开文件
O_CREAT当目标文件不存在时,创建文件

传递方式介绍:

例如:以只写的方式打开文件,当目标文件不存在时自动创建文件,则参数设置如下:

O_WRONLY | O_CREAT

为什么这么传递??

*位图方式传参

 先写一段代码:

#define ONE 1
#define TWO (1<<1)
#define THREE (1<<2)
#define FOUR (1<<3)
#define FIVE (1<<4)void Print(int flag)
{if(flag & ONE) printf("1\n");if(flag & TWO) printf("2\n");if(flag & THREE) printf("3\n");if(flag & FOUR) printf("4\n");if(flag & FIVE) printf("5\n");
}int main()
{Print(ONE);printf("----------------------\n");Print(TWO);printf("----------------------\n");Print(ONE|TWO);printf("----------------------\n");Print(THREE|FOUR|FIVE);printf("----------------------\n");Print(ONE|TWO|THREE|FOUR|FIVE);
}

 根据代码中的宏定义,这些宏的特点就是所有位加起来只有一个1。 

 Print函数中五个if中的判断条件其实就是判断参数哪个位为1,如果传的是ONE,那么ONE与ONE&得到的就是1,为真就打印1,其余的都为假,不打印。

当带上|操作符后,相当于把两个参数的1位合并到一起,比如ONE|TWO得到的就是0011,所以在Print中就会满足两个条件flag & ONE 和 flag & TWO。

这就是位图方式传参的基本思想。


放到flags中呢?

#define O_RDONLY       0000
#define O_WRONLY       0001
#define O_RDWR         0010
#define O_CREAT        0100

之后通过&运算:

int open(arg1, arg2, arg3){if (arg2&O_RDONLY){//设置了O_RDONLY选项}if (arg2&O_WRONLY){//设置了O_WRONLY选项}if (arg2&O_RDWR){//设置了O_RDWR选项}if (arg2&O_CREAT){//设置了O_CREAT选项}//...
}

所以如果arg2=O_CREAT | O_WRONLY,即arg2=0101,arg2 & O_WRONLY =1 && arg2 & O_CREAT =1就达到了『 以只写的方式打开文件,当目标文件不存在时自动创建文件』的目的。

这就是『 位图方式传参』。

参数mode_t mode

代表创建文件的默认权限。

例如:将mode设置为0666,则创建出来的文件权限如下:

-rw-rw-rw-

但『 实际上』创建出来文件的权限值还会受到umask(文件默认掩码)的影响。

实际创建出来文件的权限为:mode减去对应位的umask值。

umask的默认值默认为0002,所以当我们设置mode值为0666时实际创建出来文件的权限为0664。

若想创建出来文件的权限值不受umask的影响,则需要在创建文件前使用umask函数将文件默认掩码设置为0。

umask(0); //将文件默认掩码设置为0

如果不需要创建新的文件,则使用两个参数的open即可。 

返回值int fd『 简要理解文件描述符』

代表打开文件的『 文件描述符』。

  • fd>0:返回的是文件描述符。
  • fd==-1:代表打开文件失败。

一个进程可以打开多个文件:        

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
int main()
{umask(0);int fd1 = open("log1.txt", O_RDONLY | O_CREAT, 0666);int fd2 = open("log2.txt", O_RDONLY | O_CREAT, 0666);int fd3 = open("log3.txt", O_RDONLY | O_CREAT, 0666);int fd4 = open("log4.txt", O_RDONLY | O_CREAT, 0666);int fd5 = open("log5.txt", O_RDONLY | O_CREAT, 0666);printf("fd1:%d\n", fd1);printf("fd2:%d\n", fd2);printf("fd3:%d\n", fd3);printf("fd4:%d\n", fd4);printf("fd5:%d\n", fd5);return 0;
}

 为什么是从3开始呢?

我们刚才讲进程默认会打开三个输入输出流:标准输入流、标准输出流、标准错误流。

所以0、1、2分别代表了它们。

从而我们得到文件描述符的分配规则:

找到当前没有被使用的最小的下标,作为新的文件描述符。 


2.2close

close是关闭文件的系统调用接口。

int close(int fd);//参数fd是文件描述符
  • 关闭文件成功返回0;
  • 关闭文件失败返回-1。

2.3write 

write是写入文件的系统调用接口。

ssize_t write(int fd, const void *buf, size_t count);

功能:将buf位置开始向后count字节的数据写入文件描述符为fd的文件当中。

  • 写入成功,返回写入数据的字节个数。
  • 写入失败,返回-1。

例如: 

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{int fd = open("log.txt", O_WRONLY | O_CREAT, 0666);if (fd < 0){perror("open");return 1;}const char* msg = "hello syscall\n";for (int i = 0; i < 5; i++){write(fd, msg, strlen(msg));}close(fd);return 0;
}

2.4read

read是读取文件的系统调用接口。

ssize_t read(int fd, void *buf, size_t count);

功能:从文件描述符为fd的文件读取count字节的数据到buf位置当中。

  • 读取成功,返回读取数据的字节个数。
  • 读取失败,返回-1。

例如:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{int fd = open("log.txt", O_RDONLY);if (fd < 0){perror("open");return 1;}char ch;while (1){ssize_t s = read(fd, &ch, 1);if (s <= 0){break;}write(1, &ch, 1); //向文件描述符为1的文件写入数据,即向标准输出流(显示器)写入数据}close(fd);return 0;
}

当然对于文件管理来说还有很多需要讲解的细节,博主会放到下一篇文章中详细讲解,下一篇文章会深入学习『 Linux系统是如何管理文件的』,『 文件描述符在其中又扮演了怎样的角色』,『 怎么理解Linux下一切皆文件』等等内容,本篇文章只是文件部分的简单开头,主要目的是为了『 作铺垫』,更多内容,请持续关注博主Linux系列文章。 

=========================================================================

如果你对该系列文章有兴趣的话,欢迎持续关注博主动态,博主会持续输出优质内容

🍎博主很需要大家的支持,你的支持是我创作的不竭动力🍎

🌟~ 点赞收藏+关注 ~🌟

=========================================================================

相关文章:

【Linux】文件周边001之系统文件IO

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 目录 前言 1.C语言文件IO 1.1…...

防火墙接口配置实验

1、搭建拓扑 2、给云端添加网络&#xff0c;来实现真机与虚拟机的连接 3、 给防火墙g0/0/0口配置IP&#xff0c;由于我云端绑定的是192.168.100.10&#xff0c;所以这里IP配置为192.168.100.1/24,使用命令开启防火墙远程连接的服务&#xff0c;之后便可通过web远程登陆防火墙 …...

《WebKit 技术内幕》学习之五(4): HTML解释器和DOM 模型

4 影子&#xff08;Shadow&#xff09;DOM 影子 DOM 是一个新东西&#xff0c;主要解决了一个文档中可能需要大量交互的多个 DOM 树建立和维护各自的功能边界的问题。 4.1 什么是影子 DOM 当开发这样一个用户界面的控件——这个控件可能由一些 HTML 的标签元素…...

SpringBoot+Vue充电桩管理系统 附带详细运行指导视频

文章目录 一、项目演示二、项目介绍三、运行截图四、主要代码1. 分页获取预约数据代码2.保存预约信息代码3.修改订单状态代码 一、项目演示 项目演示地址&#xff1a; 视频地址 二、项目介绍 项目描述&#xff1a;这是一个基于SpringBootVue框架开发的充电桩管理系统。首先&…...

【数据结构】二叉树算法讲解(定义+算法原理+源码)

博主介绍&#xff1a;✌全网粉丝喜爱、前后端领域优质创作者、本质互联网精神、坚持优质作品共享、掘金/腾讯云/阿里云等平台优质作者、擅长前后端项目开发和毕业项目实战✌有需要可以联系作者我哦&#xff01; &#x1f345;附上相关C语言版源码讲解&#x1f345; &#x1f44…...

Vue3基础:挂载事例方法.mount()是什么?根组件模板又是什么?

.mount() <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Vue 3 演示</title> </head>…...

Unity 面试篇|(七)Unity渲染与Shader篇 【全面总结 | 持续更新】

目录 1.问一个Terrain&#xff0c;分别贴3张&#xff0c;4张&#xff0c;5张地表贴图&#xff0c;渲染速度有什么区别&#xff1f;为什么&#xff1f;2.什么是LightMap&#xff1f;3.MipMap是什么&#xff0c;作用&#xff1f;4.请问alpha test在何时使用&#xff1f;能达到什么…...

记录一些多维数组的方法

文章目录 前言一、获取多维数组的数据二、多维数组自带的方法总结 前言 验证过程中&#xff0c;我们经常会用到多维数组存储数据&#xff0c;本文主要记录一下&#xff0c;如何去获取我们需要的数据&#xff0c;以及多维数组自带的一些方法。 一、获取多维数组的数据 获取多维…...

Linux:gcc的相关知识

目录 gcc的翻译&#xff08;编译&#xff09;过程&#xff1a; 预处理&#xff1a; 条件编译&#xff1a; 编译&#xff1a; 汇编&链接&#xff1a; 什么是链接&#xff1f; 安装静态库&#xff1a; 静态库的使用&#xff1a; 动态静态的对比&#xff1a; 优缺对比…...

Linux的奇妙冒险———vim的用法和本地配置

vim的用法和本地配置 一.vim的组成和功能。1.什么是vim2.vim的多种模式 二.文本编辑&#xff08;普通模式&#xff09;的快捷使用1.快速复制&#xff0c;粘贴&#xff0c;剪切。2.撤销&#xff0c;返回上一步操作3.光标的控制4.文本快捷变换5.批量化操作和注释 三.底行模式四.v…...

微信小程序底部按钮适配iPhoneX以上,显示遮挡问题

只需要在给底部按钮加个样式 /* 底部导航栏容器 */ .button-box {/* 使用 safe-area-inset-bottom 属性适配 iPhone X 及以上型号设备 */padding-bottom: constant(safe-area-inset-bottom);padding-bottom: env(safe-area-inset-bottom);/* 其他样式属性 */ }iPhone6/7/8效果 …...

Qt容器QMap(映射)

插入数据 QMap<QString,QString> infoMap; //第一个是key 第二个是valueinfoMap.insert("王祖蓝","163cm");infoMap.insert("Anglebaby","168cm");infoMap["易烊千玺"] "173cm(成长中)";infoMap["姚…...

AI时代的创新工具:如何利用AI生成独具个性的XMind思维导图?

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff0c;物联网搬砖工一名&#xff0c;致力于为大家淘出更多好用的AI工具&#xff01; 背景 随着互联网的发展&#xff0c;越来越多的人开始使用Markdown来编写文档。Markdown是一种轻量级的标记语言&#xff0c;它允许人们使…...

【每日一题】最长交替子数组

文章目录 Tag题目来源解题思路方法一&#xff1a;双层循环方法二&#xff1a;单层循环 写在最后 Tag 【双层循环】【单层循环】【数组】【2024-01-23】 题目来源 2765. 最长交替子数组 解题思路 两个方法&#xff0c;一个是双层循环&#xff0c;一个是单层循环。 方法一&am…...

gin数据解析和绑定

1. Json 数据解析和绑定 客户端传参&#xff0c;后端接收并解析到结构体 package mainimport ("github.com/gin-gonic/gin""net/http" )// 定义接收数据的结构体 type Login struct {// binding:"required"修饰的字段&#xff0c;若接收为空值…...

TCP服务器最多支持多少客户端连接

目录 一、理论数值 二、实际部署 参考 一、理论数值 首先知道一个基础概念&#xff0c;对于一个 TCP 连接可以使用四元组&#xff08;src_ip, src_port, dst_ip, dst_port&#xff09;进行唯一标识。因为服务端 IP 和 Port 是固定的&#xff08;如下图中的bind阶段&#xff0…...

UML类图学习

UML类图学习 UML类图是描述类之间的关系概念1.类(Class)&#xff1a;使用三层矩形框表示2.接口(interface)&#xff1a;使用两层矩形框表示&#xff0c;与类图主要区别在于顶端有<<interface>>显示3、继承类&#xff08;extends&#xff09;&#xff1a;用空心三角…...

死锁面试题详解

什么是死锁&#xff1f; 死锁是指两个或多个进程在执行过程中&#xff0c;因争夺资源而造成的一种相互等待的现象&#xff0c;如果没有外力干涉&#xff0c;这些进程将永远无法继续执行 死锁通常发生在多个进程试图同时访问同一资源而无法获取的情况下&#xff0c;例如&#…...

【rust/bevy】使用points构造ConvexMesh

目录 说在前面问题提出Rapier具体实现参考 说在前面 操作系统&#xff1a;win11rust版本&#xff1a;rustc 1.77.0-nightlybevy版本&#xff1a;0.12github&#xff1a;这里 问题提出 在three.js中&#xff0c;可以通过使用ConvexGeometry从给定的三维点集合生成凸包(Convex Hu…...

【C语言】string.h——主要函数总结

string.h主要定义了字符串处理函数和内存操作函数。 字符串处理函数 strlen() 功能&#xff1a;strlen()函数返回字符串的字节长度&#xff0c;不包括末尾的空字符\0。 函数原型&#xff1a;size_t strlen(const char* s); 返回值&#xff1a;返回的是size_t类型的无符号整…...

Fay数字人框架全攻略:从技术原理到商业落地的完整实践指南

Fay数字人框架全攻略&#xff1a;从技术原理到商业落地的完整实践指南 【免费下载链接】Fay Fay 是一个开源的数字人类框架&#xff0c;集成了语言模型和数字字符。它为各种应用程序提供零售、助手和代理版本&#xff0c;如虚拟购物指南、广播公司、助理、服务员、教师以及基于…...

SenseVoice-Small ONNX标点评测:CT-Transformer在不同文本长度下的F1值

SenseVoice-Small ONNX标点评测&#xff1a;CT-Transformer在不同文本长度下的F1值 1. 引言 语音识别技术已经深入到我们工作和生活的方方面面&#xff0c;从手机语音助手到会议纪要自动生成&#xff0c;都离不开它的身影。然而&#xff0c;对于很多开发者和小型团队来说&…...

BM3D算法深度解析:为什么它至今仍是图像去噪的黄金标准?

BM3D算法深度解析&#xff1a;为什么它至今仍是图像去噪的黄金标准&#xff1f; 在数字图像处理领域&#xff0c;去噪技术一直是研究的热点与难点。从早期的均值滤波到小波变换&#xff0c;再到如今的深度学习&#xff0c;各种方法层出不穷。然而&#xff0c;在这片技术迭代的浪…...

革新性网页资源捕获工具:猫抓全方位媒体嗅探与下载解决方案

革新性网页资源捕获工具&#xff1a;猫抓全方位媒体嗅探与下载解决方案 【免费下载链接】cat-catch 猫抓 chrome资源嗅探扩展 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 猫抓浏览器插件是一款革新性的开源资源嗅探工具&#xff0c;能够智能识别并捕获…...

Cursor Pro激活器技术深度解析:突破API限制的逆向工程实践

Cursor Pro激活器技术深度解析&#xff1a;突破API限制的逆向工程实践 【免费下载链接】cursor-free-vip [Support 0.45]&#xff08;Multi Language 多语言&#xff09;自动注册 Cursor Ai &#xff0c;自动重置机器ID &#xff0c; 免费升级使用Pro 功能: Youve reached your…...

如何快速上手BepInEx:3个高效秘诀解锁Unity游戏插件开发

如何快速上手BepInEx&#xff1a;3个高效秘诀解锁Unity游戏插件开发 【免费下载链接】BepInEx Unity / XNA game patcher and plugin framework 项目地址: https://gitcode.com/GitHub_Trending/be/BepInEx 想象一下&#xff0c;你心爱的Unity游戏缺少某个功能&#xff…...

动态规划 -- 最长公共子序列

最长公共子序列的结构设序列 X{x1,x2,…,x m} 和 Y{y1,y2,…,y n} 的最长公共子序列为 Z{z1,z2,…,z k}&#xff0c;则有以下结论&#xff1a;若 x my n&#xff0c;则 z kx my n&#xff0c;且 Z k−1&#xff08;即 Z 去掉最后一个元素 z k 后的子序列&#xff09;是 X m−1&…...

Qt实战:QGroupBox和QButtonGroup的5个实用技巧(附完整代码)

Qt实战&#xff1a;QGroupBox和QButtonGroup的5个实用技巧&#xff08;附完整代码&#xff09; 在Qt界面开发中&#xff0c;QGroupBox和QButtonGroup是两个看似简单却暗藏玄机的组件。很多开发者只停留在基础使用层面&#xff0c;却不知道它们能实现更复杂的交互逻辑和界面优化…...

如何用G-Helper实现CPU降压调优:华硕笔记本用户的散热与续航提升指南

如何用G-Helper实现CPU降压调优&#xff1a;华硕笔记本用户的散热与续航提升指南 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops. Control tool for ROG Zephyrus G14, G15, G16, M16, Flow X13, Flow X16, TUF, Strix, Scar and other mo…...

手把手教你用GDFN模块改进图像处理(附Restormer实战代码)

手把手教你用GDFN模块改进图像处理&#xff08;附Restormer实战代码&#xff09; 在计算机视觉领域&#xff0c;图像处理技术正经历着从传统方法到深度学习范式的深刻变革。作为这一变革的前沿代表&#xff0c;Restormer框架凭借其创新的Transformer架构&#xff0c;在图像去噪…...