【Linux】从零认识文件操作

news2024/10/11 6:24:06

在这里插入图片描述
送给大家一句话:

要相信,所有的不美好都是为了迎接美好,所有的困难都会为努力让道。
—— 简蔓《巧克力色微凉青春》

开始理解基础 IO 吧!

  • 1 前言
  • 2 知识回顾
  • 3 理解文件
    • 3.1 进程和文件的关系
    • 3.2 文件的系统调用
      • open
      • write
      • 文件 fd 值
    • 3.3 语言层如何理解
  • Thanks♪(・ω・)ノ谢谢阅读!!!
  • 下一篇文章见!!!

1 前言

在C语言已经掌握文件操作的一些接口,接下来我们来从操作系统的层面来理解文件操作!!!
基础IO的篇章我们将讲解以下内容:

  1. 复习C文件IO相关操作
  2. 认识文件相关系统调用接口
  3. 认识文件描述符,理解重定向
  4. 对比fd和FILE,理解系统调用和库函数的关系
  5. 理解文件系统中inode的概念
  6. 认识软硬链接,对比区别
  7. 认识动态静态库,学会结合gcc选项,制作动静态库

2 知识回顾

C语言中要进行文件操作,就一定要先打开这个文件:fopen(),并用一个文件指针来接收
例如:FILE* fp = fopen("log.txt","w")
打开也有可能会失败,所以还要检查fp是否为空指针。当我们使用完文件之后一定一定要关闭文件:fclose(fp)

我们要进行文件操作,前提是我们的程序跑起来了!文件打开和关闭,是CPU在执行我们的程序。所以可以推断出来:

  • 打开文件的本质是进程打开文件!!!
  • 文件没有被打开的时候,文件在哪里??? 当然是磁盘了
  • 进程可以打开多个文件!!! (系统中同样可以存在多个进程) 很多的情况下,OS内部存在大量被打开的文件!那操作系统就要对打开的文件进行管理!! (那么每个打开的文件在OS内部都存在一个对应描述文件属性的结构体,类似PCB
  • 文件 = 属性 + 内容
  • 注意文件写入方式:
r   Open text file for reading.
	The stream is positioned at the beginning of the file.
	
r+  Open for reading and writing.
    The stream is positioned at the beginning of the file.
    
w   Truncate(缩短) file to zero length or create text file for writing.
    The stream is positioned at the beginning of the file.
    
w+  Open for reading and writing.
	The file is created if it does not exist, otherwise it is truncated.
	The stream is positioned at the beginning of the file.
	
a   Open for appending (writing at end of file).
    The file is created if it does not exist.
    The stream is positioned at the end of the file.
    
a+  Open for reading and appending (writing at end of file).
    The file is created if it does not exist. The initial file position
    for reading is at the beginning of the file,
    but output is always appended to the end of the file.

3 理解文件

3.1 进程和文件的关系

3.2 文件的系统调用

open

各个语言的文件接口基本都是不一样的,那么语言之间有没有共性呢???
我们来看一个系统调用:open(),我们先认识使用一下:

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

第一个参数和C语言fopen的第一个参数一致(表示文件路径或当前目录下的文件名)
第二个参数表示想怎样打开文件,传入的是标志位
第三个参数表示创建文件的权限
会返回一个数字表示是否打开成功。

  1 #include<sys/types.h>  
  2 #include<sys/stat.h>  
  3 #include<stdio.h>  
  4 #include<fcntl.h>  
  5   
  6 int main()  
  7 {  // 以只读形式打开 , 文件不存在就创建
  8   int fd = open("log.txt",O_WRONLY|O_CREAT);  
  9   if(fd < 0)  
 10   {  
 11     perror("open");  
 12     return 1;  
 13   }                                                                                                                                                                           
 14 }   

运行代码:
在这里插入图片描述
可以看的我们成功创建了一个新文件,但是文件的权限好像不对(这里因为我们没有设置对应权限,所以是乱码!)
所以才有了第三个参数,来帮助我们确定权限
int fd = open("log.txt",O_WRONLY|O_CREAT,0666); 我们在来看看
在这里插入图片描述
哎呦???怎么权限还是不对,我们设置的是666应该是rw-rw-rw-啊???这是因为创建的文件会收到文件掩码的影响:
在这里插入图片描述
所以会出现这样的情况,那怎么解决呢?

我们可以使用umask()系统调用,动态修改掩码值(只在该进程中起作用),来达到我们预期的结果:

  1 #include<sys/types.h>
  2 #include<sys/stat.h>
  3 #include<stdio.h>
  4 #include<fcntl.h>
  5 
  6 int main()
  7 {
  8   umask(0);                                                                                                                                                                   
  9   int fd = open("log.txt",O_WRONLY|O_CREAT,0666);                                                             
 10   if(fd < 0)                                                                                                  
 11   {                                                                                                           
 12     perror("open");                                                                                           
 13     return 1;                                                                                                 
 14   }                                                                                                           
 15 } 

这样就创建出来我们预期的效果了!!!

我们再来看看 flag 标志位,它是一个32位的整数,每个比特位代表一个对应功能(OS常用的系统调用接口的常用方法),也就是位图!!!每个宏定义都是一个对应比特位设置为1,想要实现多个功能就进行 | 按位与操作就可以了!!!

常用的标志位参数:
O_RDONLY: 只读打开
O_WRONLY: 只写打开
O_RDWR : 读,写打开
上面三个常量,必须指定一个且只能指定一个

O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限
O_APPEND: 追加写

write

接下来我们写入来试试。

  1 #include<sys/types.h>
  2 #include<sys/stat.h>
  3 #include<stdio.h>
  4 #include<fcntl.h>
  5 
  6 int main()
  7 {
  8   umask(0);
  9   int fd = open("log.txt",O_WRONLY|O_CREAT,0666);
 10   if(fd < 0)
 11   {
 12     perror("open");
 13     return 1;
 14   }
 15 
 16   const char* message = "hello linux file!\n";
 17   write(fd , message,strlen(message));
 18 
 19   close(fd);
 20   return 0;                                                                                                                                                                   
 21 }    

这样就成功写入进去了(注意没有写入\0哦)
在这里插入图片描述
但是我们在写入aaaa时会发现,原本文件并没有清空,也就是open默认不会清空文件!!!,这时我们加入新的标记位O_TRUNC,就能打开文件就清空了!现在就不会出现叠加的情况了!通过不同的标识位可以做到不同功能(比如追加写入)

文件 fd 值

接下来我们来认识一下文件fd:

#include<sys/types.h>  
  2 #include<sys/stat.h>  
  3 #include<stdio.h>  
  4 #include<fcntl.h>  
  5 #include<string.h>  
  6   
  7 int main()  
  8 {  
  9   int fda = open("loga.txt",O_WRONLY|O_CREAT|O_TRUNC);  
 10   printf("fda: %d\n",fda);  
 11   
 12   int fdb = open("logb.txt",O_WRONLY|O_CREAT|O_TRUNC);  
 13   printf("fda: %d\n",fdb);  
 14     
 15   int fdc = open("logc.txt",O_WRONLY|O_CREAT|O_TRUNC);  
 16   printf("fda: %d\n",fdc) ;   
 17   return 0
 18 }  

来看效果:
在这里插入图片描述
每个文件都有对应的不同的fd值(类似进程的 pid),为什么是从3开始的呢,因为0 1 2 ,都是已经设置好的文件:

  • 0 : 标准输入 – 键盘
  • 1 : 标准输出 – 显示器
  • 2 : 标准错误 – 显示器

在语言层(比如C语言),也会默认打开这三个(stdin stdout stderr)。我们使用文件对应的fd值,也可以实现写入操作了。
那么在操作系统内部,是如何实现的呢?
文件的管理类似进程管理,会有对应的struct filel来进行管理,而且多个进程可能打开同一个文件,所以进程里也一定有管理该进程打开的文件的结构体(struct files_struct),里面包含一个指针数组,每个指针都指向对应的文件,数组的下标也就是每个文件的fd值,所以上层的系统调用使用fd值(数组下标)就能访问对应文件!!!
在这里插入图片描述
这时也就可以总结一下open系统调用做了哪些事情:

  1. 创建file
  2. 开辟文件缓冲区的空间,加载文件数据
  3. 查进程的文件描述符表(struct files_struct *file)
  4. file 地址,填入对应表的下表中
  5. 返回下标(fd)

3.3 语言层如何理解

C语言中FILE其实是一个结构体类型,内部一定会封装文件fd!!!来看

#include<sys/types.h>  
  2 #include<sys/stat.h>  
  3 #include<stdio.h>  
  4 #include<fcntl.h>  
  5 #include<string.h>  
  6   
  7 int main()  
  8 {  
  9   
 10   printf("stdin->fd: %d\n",stdin->_fileno);  
 11   printf("stdin->fd: %d\n",stdout->_fileno);  
 12   printf("stdin->fd: %d\n",stderr->_fileno);  
 13   
 14   FILE* fp = fopen("log.txt","w");  
 15   if(fp == NULL) return 1;  
 16   printf("fd : %d\n",fp->_fileno);  
 17   
 18   FILE* fp1 = fopen("log1.txt","w");  
 19   if(fp1 == NULL) return 1;  
 20   printf("fd : %d\n",fp1->_fileno);  
 21   
 22   FILE* fp2 = fopen("log2.txt","w");  
 23   if(fp2 == NULL) return 1;  
 24   printf("fd : %d\n",fp2->_fileno);    
 25   return 0
 26 }

来看运行效果:
在这里插入图片描述
怎么样,我们的猜测没有问题!!!所以语言层的文件操作函数,本质底层是对系统调用的封装!通过不同标志位的封装来体现w r a+等不同打开类型!
我们在使用文件操作时,一般都要使用语言层的系统调用,来保证代码的可移植性。因为不同系统的系统调用可以会不一样!

下一篇文章我们来看文件操作的应用!!!

Thanks♪(・ω・)ノ谢谢阅读!!!

下一篇文章见!!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

问题解决:写CSDN博文时图片大小不适应,不清晰,没法排版

项目环境&#xff1a; Window10&#xff0c;Edge123.0.2420.65 问题描述&#xff1a; 当我在CSDN写博文的时候&#xff0c;会经常插入一些图片&#xff0c;但有时候我插入的图片太大了&#xff0c;影响了整体排版。 比如我加入了一张图片&#xff0c;就变成了下面这个样子&…

前端三剑客 —— CSS (第三节)

目录 上节回顾&#xff1a; 1.CSS使用有以下几种样式; 2.选择器 1.基本选择器 2.包含选择器 3.属性选择器 [] 4.伪类选择器 &#xff1a; 5.伪元素选择器 ::before :after 3.常见样式的使用 常见样式参考表 一些特殊样式 媒体查询 自定义字体 变换效果 translate&…

OpenHarmony实战:小型系统平台驱动移植

在这一步&#xff0c;我们会在源码目录//device/vendor_name/soc_name/drivers目录下创建平台驱动。 建议的目录结构&#xff1a; device ├── vendor_name │ ├── drivers │ │ │ ├── common │ │ │ ├── Kconfig # 厂商驱动内核菜单入口 │ …

win11安装wsl报错:无法解析服务器的名称或地址

一 说明 项目开发中&#xff0c;需要用到wsl&#xff0c;因此根据wsl官方&#xff08;WSL安装教程&#xff09;命令 wsl --install 进行wsl的安装。而本文主要是记录自己在安装wsl中遇到的问题 “无法解析服务器的名称或地址” 的解决办法。 二 方法一&#xff1a;更改DNS&…

RUST语言基本数据类型认识

1.RUST的基本数据类型参考: 2.使用RUST数据类型声明变量并赋值: let a:i81;//8位有符号整数let a1:u82;//8位无符号整数let b:i161;//16位有符号整数let b1:u162;//16位无符号整数let c:i321;//32位有符号整数let c1:u322;//32位无符号整数let d:i641;//64位有符号整数let d1:u…

【web】nginx+php-fpm云导航项目部署-(简版)

一、yum安装nginx yum -y install nginx 二、php环境安装 2.1 php安装 yum -y install php 2.2 php-fpm安装 yum -y install php-fpm 注&#xff1a;PHP在 5.3.3 之后已经讲php-fpm写入php源码核心了。 2.3 项目依赖的php-xml和php-xmlrpc安装 yum -y install php-…

在Vue2里面加载AntvL7

1、代码块 <template><div ref"mapContainer" style"width: 800vh; height: 100vh; align-items: center; justify-content: center"></div> </template><script> export default {mounted() {this.initMap();},methods: {…

openplc Linux 地址映射io,读写驱动数据等使用记录

1. 上一篇记录 openplc使用C语言文件读写驱动实现基本流程。 openPLC_Editor C语言编程 在mp157 arm板上调用io等使用记录_openplc c 编程-CSDN博客 2. 下面通过映射地址的方式控制io和读写驱动数据。 在runtime 环境的 hardware 硬件配置中 选择 python on Linux(PSM)&#…

Redis常用命令补充和持久化

一、redis 多数据库常用命令 1.1 多数据库间切换 1.2 多数据库间移动数据 1.3 清除数据库内数据 1.4 设置密码 1.4.1 使用config set requirepass yourpassword命令设置密码 1.4.2 使用config get requirepass命令查看密码 二、redis高可用 2.1 redis 持久化 2.1.1 持…

PS从入门到精通视频各类教程整理全集,包含素材、作业等(7)复发

PS从入门到精通视频各类教程整理全集&#xff0c;包含素材、作业等 最新PS以及插件合集&#xff0c;可在我以往文章中找到 由于阿里云盘有分享次受限制和文件大小限制&#xff0c;今天先分享到这里&#xff0c;后续持续更新 PS敬伟01——90集等文件 https://www.alipan.com/s…

日历插件fullcalendar【前端】

日历插件fullcalendar【前端】 前言版权开源推荐日历插件fullcalendar一、下载二、初次使用日历界面示例-添加事件&#xff0c;删除事件 三、汉化四、动态数据五、前后端交互1.环境搭建-前端搭建2.环境搭建-后端搭建3.代码编写-前端代码fullcalendar.htmlfullcalendar.js 4.代码…

vue项目引入微信sdk: npm install weixin-js-sdk --save报错

网上查到要用淘宝的镜像 同事告知旧 域名&#xff1a;https://registry.npm.taobao.org/已经不能再使用 使用 npm config set registry http://registry.npmmirror.com

DTFT及其反变换的直观理解

对于离散时间傅里叶变换(DTFT)及其反变换的讲解&#xff0c;教材里通常会先给出DTFT正变换的公式&#xff0c;再举个DTFT的简单变换例子&#xff0c;推导一下DTFT的性质&#xff0c;然后给出DTFT反变换的公式&#xff0c;再证明一下正变换和反变化的对应关系。总的来说就是&…

MySQL版本特性和存储引擎选择

MySQL版本特性和存储引擎选择 1.说一下MySQL 5.5 5.6 5.7 8.0 各个版本的特性 MySQL 5.5 优点: 稳定性&#xff1a;5.5版本是长期支持&#xff08;LTS&#xff09;版本&#xff0c;因此它非常稳定&#xff0c;被广泛部署在生产环境中。兼容性&#xff1a;与旧版本的MySQL和…

索引的概念

索引的概念    1.索引是一种可选的与表相关的数据库对象&#xff0c;用于提高数据的查询效率。    2.索引是一种有序的数据结构。    3.如果一个表没有创建索引&#xff0c;则对该表进行查询时需要进行全表扫描&#xff1b;如果创建了索引&#xff0c;则在有条件查询时…

http模块 设置资源类型(mime类型)

虽然浏览器自带websocket功能它会根据响应回来的内容自动去判断资源类型&#xff0c;但是我们加上了mime类型判断代码会更加规范些 一、mime类型概念&#xff1a; 媒体类型是一种标准&#xff0c;它用来表示文档。文件、字节流的性质和格式。HTTP服务可以设置响应头Content-T…

WebKit简介

1、简介&#xff08;WebKit&#xff09; WebKit 是一个开源的浏览器引擎&#xff0c;最初由苹果公司基于KHTML&#xff08;K Desktop Environment的HTML渲染引擎&#xff09;开发&#xff0c;并广泛应用于Safari浏览器&#xff0c;后来也被其他多款浏览器和应用采用。WebKit负…

【管理咨询宝藏48】AA银行信息科技提升分析报告

本报告首发于公号“管理咨询宝藏”&#xff0c;如需阅读完整版报告内容&#xff0c;请查阅公号“管理咨询宝藏”。 【管理咨询宝藏48】AA银行信息科技提升分析报告 【格式】PPT版本&#xff0c;可编辑 【关键词】战略规划、商业分析、管理咨询 【强烈推荐】这是一套市面上非常…

【介绍什么是DDOS】

&#x1f308;个人主页:程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

Swin_transformer模型解析

目录 •1、网络整体框架 •2 、Patch Merging •3 、W-MSA MSA模块计算量 W-MSA模块计算量 •4、 SW-MSA •5 、Relative Position Bias •1、网络整体框架 •2 、Patch Merging 这里看着挺复杂&#xff0c;其实就相当于先对特征图进行LayerNorm&#xff0c;然后再进行一…