【文件fd】C++文件操作 | 详解系统调用接口文件操作 | 系统调用接口库函数

news2024/11/19 1:25:04

目录

1.回顾理解&引出问题

2.C++文件操作

3.系统调用文件操作

3.0准备工作

3.1版本1☞open

3.2版本2☞文件权限

3.3版本3☞权限掩码

3.4版本3☞标记位传参

3.5版本4☞close

3.6版本5☞write

3.7flags选项  

3.7.1 O_WRONLY | O_CREAT

3.7.2 O_WRONLY | O_CREAT | O_TRUNC

3.7.3 O_WRONLY | O_CREAT | O_APPEND

3.7.4 flags选项和C语言的"w""a"方式 二者存在什么关系❓


1.回顾理解&引出问题

  • C语言文件操作,写代码/编码的时候,调用fopen,文件根本没有被打开。只有当可执行程序,形成进程,在CPU上执行,运行到fopen那行代码的时候,文件才被动态的打开了。语言编译好,运行起来就是进程。
  • 操作文件的本质:进程在操作文件。是进程和文件的关系。
  • 没有被打开的文件是存在于磁盘上的。
  • 磁盘是一个外部设备。外设是硬件。磁盘是硬件设备。
  • 向文件中写入,向磁盘当中写入,本质就是向硬件当中写入。
  • 用户向硬件写入是不被允许的❗用户没有权力直接向硬件写入和访问。
  • 硬件的管理者是操作系统OS。必须通过OS写入和访问。用的是fopen/fread/fwrite等的的C语言库函数。

  • 为了用户有更好的文件操作体验(用户有写入和访问硬件的需求)OS支持------>给用户提供系统调用接口(OS不相信任何人)------>用户用都是不同语言提供的不同库函数文件操作接口-------->意味着我们使用的C/C++等语言都是对系统调用的封装的库函数

  • 访问文件,用户不仅可以使用各种语言提供的各种库函数,可以使用系统调用❗

  • C/C++等语言的文件操作库函数都是对系统调用接口的封装。

  • 怎么封装❓为什么封装❓

  • 上层语言对文件访问是不一样的。难道我们每学一个语言,我们都需要去学习这个语言的文件操作吗❓

2.C++文件操作

 C/C++等其他语言,访问文件的方式,文件操作的库函数接口有些不一样❗

3.系统调用文件操作

3.0准备工作

先用和认识系统调用的文件操作。 

系统调用手册查询:2号手册。

 

3.1版本1☞open

  • man 2 open
  • 头文件:#include <sys/types.h>  #include <sys/stat.h>   #include <fcntl.h>
  • Open打开文件操作,两种写法(两个参数/三个参数)
  • 两个参数:int open(const char *pathname, int flags);
  • 三个参数:int open(const char *pathname, int flags, mode_t mode);
  • 两个参数的写法:一般用来操作已经存在的文件

  • 三个参数的写法:一般用来操作没有存在的文件

  • 第一个参数pathname:打开的文件是谁。可以带路径,也可以只有文件名(如果只有文件名,此文件就在在当前的路径下创建文件☞进程的当前工作路径)

  • 第二个参数flags:代表的是怎么去创建文件,文件打开方式。flage是整数,但是它可以传递很多标记位。❓flags后面详谈

  • 第三个参数mode:设置文件权限。

  • 返回值:一旦文件被打开,成功就会返回一个整数☞文件描述符fd☞一个新的数字。失败,-1被返回和错误码被设置。


【版本1】log.txt文件确实在进程的当前工作路径被创建,但是创建的log.txt文件的权限是乱码/不正确。❗所以在LinuxOS中新建文件,必须告知新建文件的起始权限是什么。

【版本1】

  1 #include<stdio.h>
  2 #include <sys/types.h>
  3 #include <sys/stat.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 }

【运行结果】

3.2版本2☞文件权限

  • 运行结果是0664而不是0666❓为什么是0664❓
  • 因为在Linux系统中存在权限掩码。0666经过☞权限掩码0002☞变成了0664(之前讲过)如果就想创建文件的权限为0666,不要权限掩码。动态设置当前进程创建文件的权限掩码。
 1: myfile.c
  1 #include<stdio.h>
  2 #include <sys/types.h>
  3 #include <sys/stat.h>
  4 #include <fcntl.h>
  5 
  6 int main()
  7 {
  8   int fd = open("log.txt",O_WRONLY | O_CREAT,0666);//给出文件权限0666                                                                   
  9   if(fd < 0)                                                                    
 10   {                                                                             
 11     perror("open");                                                             
 12     return 1;                                                                   
 13   }                                                                             
 14 }       

3.3版本3☞权限掩码

  • man 2 umask
  • 让可执行程序在运行的时候,形成进程,进程的权限掩码被动态的设置。使创建的文件log.txt的权限掩码改变了。(从使用系统OS的权限☞使用自定义的权限掩码)
  • umask是代码编译形成可执行程序,运行时候,形成进程。动态调整当前进程创建文件时的权限掩码
  • 系统还是存在自己的权限掩码。就近原则。有系统就用系统的,有自己设置,自定义的,的就用自己设置的。

 1: myfile.c+ 
  1 #include<stdio.h>
  2 #include <sys/types.h>
  3 #include <sys/stat.h>
  4 #include <fcntl.h>
  5 
  6 int main()
  7 {
  8   umask(0);//动态设置当前进程的权限掩码                                                                                                 
  9   int fd = open("log.txt",O_WRONLY | O_CREAT,0666);//给出文件权限0666                                           
 10   if(fd < 0)                                                                                                    
 11   {                                                                                                             
 12     perror("open");                                                                                             
 13     return 1;                                                                                                   
 14   }                                                                                                             
 15 }              

3.4版本3☞标记位传参

  • C语言学习的时候,对函数传递一个标记位(功能选项)。传递标记位可能传很多,难道我们每次都要设置很多的标记位去传参吗❓(以整数的方式传递)这种方式存在的问题:代码不好维护,且浪费时间,使用起来很不方便。
  • 标记位:一般传0/1,或者表示有或没有的概念。
  • OS设计很多系统调用接口的常见方法:一个flags整数有32个bite位。用比特位来对标志位的进行传递。flage看起来是一个整数,是32个比特位,也是一个位图。
  • 选项的本质:都是比特位为1的宏,彼此之间宏值不重复。flags整数位图☞宏☞不同选项☞不同的文件操作功能


因为OS设计很多系统调用接口的常见方法,为了更加深入的理解标志位传参。我们设计一个传递位图标记位的函数。

 1: flags.c 
  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<fcntl.h>
  4 
  5 #define ONE 1        //1 0000 0001
  6 #define TWO (1<<1)   //2 0000 0010
  7 #define THREE (1<<2) //4 0000 0100
  8 #define FOUR (1<<3)  //8 0000 1000
  9                      //  0000 1111
 10 
 11 void print(int flags)
 12 {
 13   if(flags&ONE)
 14     printf("one\n");
 15   if(flags&TWO)
 16     printf("two\n");
 17   if(flags&THREE)
 18     printf("three\n");
 19   if(flags&FOUR)
 20     printf("four\n");
 21 }
 22 
 23 int main()
 24 {
 25   print(ONE);
 26   printf("\n");
 27 
 28   print(TWO);
 29   printf("\n");
 30 
 31   print(THREE);                                            
 32   printf("\n");
 33 
 34   print(FOUR);
 35   printf("\n");
 36 
 37   print(ONE|TWO|THREE);
 38   printf("\n");
 39 
 40   print(ONE|FOUR);                                         
 41   printf("\n");
 42   
 43   print(THREE|FOUR);
 44   printf("\n");
 45   
 46   return 0;
 47 }

3.5版本4☞close

  • man 2 close
  • 参数fd文件描述符

 1: myfile.c 
  1 #include <stdio.h>                                          
  2 #include <unistd.h>  
  3 #include <sys/types.h>  
  4 #include <sys/stat.h>                   
  5 #include <fcntl.h>                      
  6                                         
  7 int main()                              
  8 {                                        
  9   umask(0);//动态设置当前进程的权限掩码   10   int fd = open("log.txt",O_WRONLY | O_CREAT,0666);//给出文>    件权限0666                              
 11   if(fd < 0)                            
 12   {                                     
 13     perror("open");                     
 14     return 1;                           
 15   }                                     
 16                                         
 17   close(fd);                            
 18   return 0;                             
 19 }                  

3.6版本5☞write

  • man 2 write
  • ssize_t write(int fd, const void *buf, size_t count);
  • write:就是把指定的缓冲区写到指定的文件里面。
  • fd 相当于FILE*类型,标定的一个文件,想往哪个文件写,就往哪个文件写。
  • buf 缓冲区起始地址
  • count 缓冲区大小
  • 注意❗strlen不需要+1,strlen是计算字符串的有效内容。字符串\0是C语言的规定+1,这里是系调用接口,只需要写入有效字符串内容即可,不需要+1。

 1: myfile.c 
  1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <sys/types.h>
  4 #include <sys/stat.h>
  5 #include <fcntl.h>
  6 #include<string.h>                                          
  7                                      
  8 int main()                           
  9 {                                      
 10   umask(0);//动态设置当前进程的权限掩码 11   int fd = open("log.txt",O_WRONLY | O_CREAT,0666);//给出文>    件权限0666                           
 12   if(fd < 0)                         
 13   {                                  
 14     perror("open");                  
 15     return 1;                        
 16   }                                  
 17                                             
 18   const char *message="hello linux file!\n";
 19   write(fd,message,strlen(message)); 
 20                                      
 21   close(fd);                         
 22   return 0;                          
 23 }                  

3.7flags选项  

3.7.1 O_WRONLY | O_CREAT

 ❓把要缓冲区的内容换,会发生什么

清晰的发现:O_WRONLY | O_CREAT 选项 使写入的方式(从头开始写)不会清空,不存在就创建。存在就从头开始写。上一次基础上从头开始写,老的内容没有被清空。

3.7.2 O_WRONLY | O_CREAT | O_TRUNC

如果文件已经存在,是常规文件且打开的文件是准备写入。会reuncated截断,把文件清空。

O_WRONLY | O_CREAT | O_TRUNC 选项是写的方式打开,不存在就创建,存在先清空。

 

 【再次证明☞就一打一关闭】

【提前往log.txt写点内容】 

 

 【文件被自动清空】

3.7.3 O_WRONLY | O_CREAT | O_APPEND

O_WRONLY | O_CREAT | O_APPEND 打开文件的时候,使用追加模式,也是写入。

 

3.7.4 flags选项和C语言的"w""a"方式 二者存在什么关系❓

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

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

相关文章

Servlet详解(超详细)

Servlet详解 文章目录 Servlet详解一、基本概念二、Servlet的使用1、创建Servlet类2、配置Servleta. 使用web.xml配置b. 使用注解配置 3、部署Web应用4、处理HTTP请求和生成响应5、处理表单数据HTML表单Servlet 6、管理会话 三、servlet生命周期1、加载和实例化2、初始化3、 请…

Python爬虫入门02:Fiddler下载使用教程

文章目录 手机抓包全攻略&#xff1a;Fiddler 工具深度解析引言Fiddler 工具简介为什么选择 Fiddler&#xff1f; 安装与配置 Fiddler步骤一&#xff1a;下载与安装步骤二&#xff1a;配置浏览器代理步骤三&#xff1a;安装 HTTPS 证书 配置手机以使用 Fiddler步骤一&#xff1…

鸿蒙应用框架开发【OpenGL三棱椎】 NDK

OpenGL三棱椎 介绍 XComponent控件常用于相机预览流的显示和游戏画面的绘制,在HarmonyOS上&#xff0c;可以配合Native Window创建OpenGL开发环境&#xff0c;并最终将OpenGL绘制的图形显示到XComponent控件。本示例基于"Native C"模板&#xff0c;调用OpenGL(Open…

wpf中团队独立开发模块和左侧2个菜单的框架演示

此篇文章和上一篇文章wpf中开发独立模块功能和左侧1个菜单的框架演示-CSDN博客的结构是一样的&#xff0c;有1点不同的是&#xff0c;左侧有2层菜单&#xff0c;所以&#xff0c;就会更加的复杂。建议&#xff0c;先看明白上一篇的内容&#xff0c;再看这篇文章&#xff0c;否则…

CSS实现表格无限轮播

<div className{styles.tableTh}><div className{styles.thItem} style{{ width: 40% }}>报警名称</div><div className{styles.thItem} style{{ width: 35% }}>开始时间</div><div className{styles.thItem} style{{ width: 25% }}>状态&…

前端三大主流框架对比

在现代前端开发中&#xff0c;React、Vue和Angular是三大流行的框架/库。它们各自有独特的优缺点&#xff0c;适用于不同的开发需求和项目规模。下面是对这三者的详细比较&#xff1a; 一、 React 简介&#xff1a; 由Facebook开发和维护&#xff0c;是一个用于构建用户界面…

亚博科技和幻尔科技的十轴IMU在Ros2 Humble下驱动后数值无限趋于0的解决方案

在做机器人导航以及建模的时候&#xff0c;考虑到多传感器融合可能会带来更好的效果&#xff0c;于是决定使用幻尔科技的十轴IMU&#xff08;其实亚博科技与幻尔科技这块IMU的内部完全一致&#xff0c;驱动代码都完全一致&#xff09;驱动后使用以下命令输出传来的四元数等数据…

自写ApiTools工具,功能参考Postman和ApiPost

近日在使用ApiPost的时候&#xff0c;发现新版本8和7不兼容&#xff0c;也就是说8不支持离线操作&#xff0c;而7可以。 我想说&#xff0c;我就是因为不想登录使用才从Postman换到ApiPost的。 众所周知&#xff0c;postman时国外软件&#xff0c;登录经常性抽风&#xff0c;…

Mike SHE里如何正确设置分区降雨

前言&#xff1a; MIKE SHE分布式水文模型现阶段用于流域洪水的项目比较多&#xff0c;因属于大尺度模型&#xff0c;基本可以模拟水循环全过程&#xff0c;包含降雨—蒸发——产汇流—地表水—地下水等。同时还可以耦合MIKE11水动力水质模型。 今天给大家介绍下MIKESHE是如何…

从零到一使用 Ollama、Dify 和 Docker 构建 Llama 3.1 模型服务

本篇文章聊聊&#xff0c;如何使用 Ollama、Dify 和 Docker 来完成本地 Llama 3.1 模型服务的搭建。 如果你需要将 Ollama 官方不支持的模型运行起来&#xff0c;或者将新版本 llama.cpp 转换的模型运行起来&#xff0c;并且想更轻松的使用 Dify 构建 AI 应用&#xff0c;那么…

进程间的通信(IPC)--管道

1.进程间通信常用的方式 1 &#xff0c;管道通信&#xff1a;有名管道&#xff0c;无名管道 2 &#xff0c;信号 - 系统开销小 3 &#xff0c;消息队列 - 内核的链表 4 &#xff0c;信号量 - 计数器 5 &#xff0c;共享内存 6 &#xff0c;内存映射 7 &#xff0c;套接…

人称“灯爷”的灯光师到底要做些什么,看看他的岗位说明书

灯光师又称“灯爷”,是摄影制作部门负责灯光设备的技术人员,一般归摄影指导调配。被尊称“爷”,可见灯光师的地位不容小觑。那么这个岗位到底要做些什么呢&#xff1f; 岗位职责&#xff1a; 1、负责公司灯光设备的调制、维护和保养&#xff1b; 2、负责各包房灯光设备的调制、…

Mac环境报错 error: symbol(s) not found for architecture x86_64

Mac 环境Qt Creator报错 error: symbol(s) not found for architecture x86_64 错误信息 "symbol(s) not found for architecture x86_64" 通常是在编译或链接过程中出现的问题。这种错误提示通常涉及到符号未找到或者是因为编译器没有找到适当的库文件或函数定义。 …

基于springboot+vue+uniapp的养老院系统小程序

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…

初识git工具~~上传代码到gitee仓库的方法

目录 1.背景~~其安装 2.gitee介绍 2.1新建仓库 2.2进行相关配置 3.拉取仓库 4.服务器操作 4.1克隆操作 4.2查看本地仓库 4.3代码拖到本地仓库 4.4关于git三板斧介绍 4.4.1add操作 4.4.2commit操作 4.4.3push操作 5.一些其他说明 5.1.ignore说明 5.2git log命令 …

ACC:Automatic ECN Tuning for High-Speed Datacenter Networks 相关知识点介绍(二)

目录 PerfTest工具 Incast traffic Incast Traffic 的原因 Incast Traffic 的影响 解决方法 流量负载 简单解释 影响因素 影响 管理方法 LINKPACK 主要特点 LinkPack 的应用 运行结果 Quantum ESPRESSO 主要特点 TensorFlow 主要特点 主要组件 Incast与qp …

Ubuntu2023.04 浏览器不能上网的问题

1.问题描述 ping www.baidu.com 是可以连接的&#xff0c;但是打开网页就是不能上网&#xff0c;但是自己查看了浏览器上面的设置&#xff0c;代理设置都是关闭的 再看了系统的设置代理也是关闭的&#xff0c;就是上不了网 解决方案&#xff1a; 455 echo $http_proxy456 e…

JavaWeb项目中动态拼接sql语句

业务需求描述&#xff1a; 图中的查询框在分条件查询用户信息列表时&#xff0c;前端可能会传回一个条件或多个条件&#xff0c;此时要对不同的条件进行sql语句的不同书写&#xff0c;前端传的情况有很多种&#xff0c;所以如果分情况写sql语句会比较死&#xff0c;并且不够灵活…

机器学习之人脸识别-使用 scikit-learn 和人工神经网络进行高效人脸识别

文章摘要 本文将介绍如何使用 Python 的 scikit-learn 库和人工神经网络&#xff08;ANN&#xff09;来识别人脸。我们将使用 LFW 数据集&#xff08;Labeled Faces in the Wild&#xff09;&#xff0c;这是一个广泛用于人脸识别基准测试的大型人脸数据库。我们将展示如何准备…

RedHat Enterprise Linux 7 YUM源(本地/网络源)配置详解

目录 一、挂载 二、建立本地源 三、建立网络源 四、验证可行性 一、挂载 ——将光盘挂载到 /mnt 下 当/mnt中有如图内容时&#xff0c;即挂载成功 若挂载光驱/dev/sr0时报错&#xff1a;mount: no medium found on /dev/sr0 解决措施&#xff1a;查看该设备状态是否全部勾选…