基础I/O--文件系统

在这里插入图片描述

文章目录

  • 回顾C文件接口
  • 初步理解文件
  • 理解文件
    • 使用和并认识系统调用
      • open
        • 概述
        • 标记位传参理解
        • 返回值
      • close
      • write
      • read
      • 总结
    • 文件描述符fd
      • 0&1&2
      • 理解

回顾C文件接口

C代码:

#include<stdio.h>    int main()    
{    FILE *fp=fopen("log.txt","w");    if(NULL==fp)    {    perror("fopen");    return 1;    }    fclose(fp);                                                                                                                            return 0;    
}  

我们要进行文件操作,前提是程序运行起来了,所谓的文件的打开和关闭是CPU执行我们的代码才被打开或者关闭的。
fopen()函数:
在这里插入图片描述

初步理解文件

打开文件:本质上是进程打开文件

文件没有被打开的时候,在哪里?在磁盘上

一个进程能打开很多文件吗? 可以

系统中可不可以存在很多进程? 可以

因此,在很对情况下,操作系统内部一定存在大量的被打开的文件
操作系统要不要对这些被打开的文件进行管理? 要
如何管理?先描述,再组织

如果在磁盘新建一个文件,里面什么内容都没有,大小为0KB,那么这个文件占用空间吗?占,因为文件对应的创建时间、文件类型等对应的文件属性都存在。
因此,文件=内容+属性

理解文件

操作文件,本质上是进程在操作文件

文件没有被打开时,文件在磁盘上,磁盘属于外部设备,磁盘本质是一个硬件,向文件写入,本质是向硬件中写入,但是用户没有权利直接向硬件写入,硬件的管理者是操系统,因此用户不能绕过操作系统直接访问硬件,必须通过操作系统写入。操作系统给用户提供系统调用,我们用的C/C++/其他语言,都是对系统调用接口的封装。
访问文件除了可以使用已经封装好的函数,还可以使用系统调用。

在这里插入图片描述

使用和并认识系统调用

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);int creat(const char *pathname, mode_t mode);

pathname: 要打开或创建的目标文件
flags: 打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成flags。
参数:
O_RDONLY: 只读打开
O_WRONLY: 只写打开
O_RDWR : 读,写打开
这三个常量,必须指定一个且只能指定一个
O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限
O_APPEND: 追加写
返回值:
成功:新打开的文件描述符
失败:-1

open 函数具体使用哪个,和具体应用场景相关,如目标文件不存在,需要open创建,则第三个参数表示创建文件的默认权限,否则,使用两个参数的open。

标记位传参理解
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>int main()
{umask(0);//system callint fd=open("log.txt",O_WRONLY|O_CREAT,0666);if(fd<0){perror("open");return 1;}
}

在这里插入图片描述

操作系统本身就有一个权限掩码,现在在代码中又写了一个权限掩码。这里使用的是代码中的掩码,就近原则。自己设置了权限掩码就用自己设置的,没有就用系统的。因此最终创建的权限掩码就是666


int flag:是32个比特位的,用比特位来进行标志位的传递。flag标志位传递本质上是一个位图。

我们来设计一个传递为图标记位的函数:

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>#define ONE 1            //1: 0000 0001
#define TWO (1<<1)       //2: 0000 0010
#define THREE (1<<2)     //3: 0000 0100
#define FOUR (1<<3)      //4: 0000 1000void print(int flag)
{if(flag&ONE) printf("one\n");if(flag&TWO) printf("two\n");if(flag&THREE) printf("three\n");if(flag&FOUR) printf("four\n");
} int main()
{print(ONE);printf("\n");print(TWO);printf("\n");print(ONE|TWO);printf("\n");print(ONE|TWO|THREE);printf("\n");print(ONE|FOUR);printf("\n");return 0;
}

在这里插入图片描述

如果我们将打印替换成其他功能,那么就可以写出一个向指定函数传递标记位的方法。

返回值
RETURN VALUE
open() and creat() return the new file descriptor, or -1 if an error occurred (in which case, errno is set appropriately).

在这里插入图片描述
返回成功,就帮我们创建一个新的文件描述符,就是一个整数,失败返回-1

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>int main()
{int fda=open("loga.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);printf("fda:%d\n",fda);int fdb=open("logb.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);printf("fdb:%d\n",fdb);int fdc=open("logc.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);printf("fdc:%d\n",fdc);int fdd=open("logd.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);printf("fdd:%d\n",fdd);return 0;}

运行结果:

在这里插入图片描述

返回值是3 4 5 6,怎么不见0 1 2呢?
因为 0 1 2分别对应标准输入(键盘)、标准输出(显示器)、标准错误(显示器)

下文有具体介绍

close

在这里插入图片描述

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

write

man 2 write可查看write函数
在这里插入图片描述

第一个参数 fd:表示待写入文件的文件描述符。

第二个参数 buf:指向待写入的文件内容。

第三个参数 count:待写入内容的大小,单位是字节。

返回值:实际上写入的字节数。

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>
int main()
{umask(0);//system callint fd=open("log.txt",O_WRONLY|O_CREAT,0666);if(fd<0){perror("open");return 1;}const char *message="hello linux file!\n";write(fd,message,strlen(message));close(fd);return 0;
}

在这里插入图片描述

会发现确实是写入了hello linux file!

将上述代码中,写入hello linux file!,修改成aaa

  const char *message="aaa";write(fd,message,strlen(message));

运行结果:

在这里插入图片描述

可见,默认不清空文件

那么,如何再次写入文件时,之前文件会被清空呢?
需要添加一个O_TRUNC

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>
int main()
{umask(0);//system callint fd=open("log.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);if(fd<0){perror("open");return 1;}const char *message="aaa";write(fd,message,strlen(message));close(fd);return 0;
}

在这里插入图片描述

运行结果:

在这里插入图片描述


追加写入:

int fd=open("log.txt",O_WRONLY|O_CREAT|O_APPEND,0666);

在这里插入图片描述

read

#include <unistd.h>ssize_t read(int fd, void *buf, size_t count);

第一个参数 fd:要读取文件的文件描述符。

第二个参数 buf:指向一段空间,该空间用来存储读取到的内容。

第三个参数 count:参数二指向空间的大小。

总结

intfd=open("log.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);

写方式打开,不存在就创建,存在就先清空


int fd=open("log.txt",O_WRONLY|O_CREAT|O_APPEND,0666);

追加形式写入

文件描述符fd

0&1&2

  • Linux进程默认情况下会有3个缺省打开的文件描述符,分别是标准输入0, 标准输出1, 标准错误2.
  • 0,1,2对应的物理设备一般是:键盘,显示器,显示器

理解

在一个操作系统中有很多文件,操作系统需要对被打开文件进行管理,也就是需要创建对应的数据结构(struct_file),对文件的管理转换成对链表的增删查改。
任何一个文件=内容+属性,磁盘中文件的属性来初始化struct_file,将文件内容写入文件内核缓存里。

一个进程可以打开多个文件,对于进程来说怎么知道被打开文件与自己有关系,因此对应的task_struct存在一个属性struct files_struct *files,指向该类型的一个对象,该类型对象记录了当前进程所打开的所有文件新信息,操作系统中就存在一个结构体:struct file_struct,里面存在一个指针数组,数组的内容指向当前进程所打开的文件结构对象,也就是指向当前进程打开的文件。我们称这个数组为文件描述符表,数组下标称为文件描述符

文件描述符fd的本质是什么?
内核进程:文件映射关系的数组下标。

在这里插入图片描述

无论读写,都必须在合适的时候,让操作系统把文件内容读到文件缓冲区中。

open在干什么??

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

读写函数本质是拷贝函数

在这里插入图片描述

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

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

相关文章

《MySQL45讲》读书笔记

重建表 alter table t engine InnoDB&#xff08;也就是recreate&#xff09;&#xff0c;而optimize table t 等于recreateanalyze&#xff0c;让表大小变小 重建表的执行流程 建立一个临时文件&#xff0c;扫描表 t 主键的所有数据页&#xff1b;用数据页中表 t 的记录生…

mac通过termius连接Linux服务器

mac上安装 linux系统 如果有 linux服务器账号密码&#xff0c;那么上一步可忽略&#xff1b; 比如&#xff1a;直接连接阿里云或腾讯云账号 1. 安装termius 链接: https://pan.baidu.com/s/1iYsZPZThPizxqtkLPT89-Q?pwdbw6j 提取码: bw6j 官网 Termius - SSH platform for …

【C++】STL — vector的接口讲解 +详细模拟实现

前言: 本章我们将学习STL中另一个重要的类模板vector… vector是表示可变大小数组的序列容器。就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素。但是又不像数组&#xff0c;它的大小是可以动态改变的本质讲&#xff0c;vector使用动态分配数组来存储它的元素v…

配电室智能巡检机器人

近年来&#xff0c;生产过程高度自动化&#xff0c;各工矿企业关键场所需定期巡检维护。但目前巡检主要靠人工&#xff0c;既耗时费力效率又低&#xff0c;且受环境等因素影响&#xff0c;巡检难以全面规范&#xff0c;隐患或问题易被忽视。在此情况下&#xff0c;如何利用现有…

ElasticSearch02(DSL查询文档,DSL处理结果,RestClient查询,旅游案例,数据聚合)【全详解】

目录 一、DSL查询文档 1. 说明 2. 文本检索 3. 精确查询 4. 地理坐标查询 5. 复合查询 6. 课堂演示 7. 小结 二、DSL处理结果 1. 排序 2. 分页 3. 高亮 4. 课堂演示 5. 小结 三、RestClient查询 1.快速入门 2.match查询 3.精确查询 4.布尔查询 5. 算分函数…

锁相环原理解析

在计算机和嵌入式系统中&#xff0c;常常要用锁相环来倍频&#xff0c;那么&#xff0c;锁相环是如何倍频的&#xff0c;其原理又是什么呢&#xff1f; 目录 1. 锁相环基本概念与构成1.1 鉴相器1.2 低通滤波器1.3 压控振荡器 2. 锁相环如何实现倍频3. 锁相环也会失效&#xff…

【前端学习——正则】

https://www.bilibili.com/video/BV1da4y1p7iZ/?spm_id_from333.337.search-card.all.click&vd_source5cef5968d539682b683e7d01b00ad01b 学习网站 https://github.com/ziishaned/learn-regex/blob/master/translations/README-cn.md

Bookends for Mac:文献管理工具

Bookends for Mac&#xff0c;一款专为学术、研究和写作领域设计的文献管理工具&#xff0c;以其强大而高效的功能深受用户喜爱。这款软件支持多种文件格式&#xff0c;如PDF、DOC、RTF等&#xff0c;能够自动提取文献的关键信息&#xff0c;如作者、标题、出版社等&#xff0c…

在M1芯片安装鸿蒙闪退解决方法

在M1芯片安装鸿蒙闪退解决方法 前言下载鸿蒙系统安装完成后&#xff0c;在M1 Macos14上打开闪退解决办法接下来就是按照提示一步一步安装。 前言 重新安装macos系统后&#xff0c;再次下载鸿蒙开发软件&#xff0c;竟然发现打不开。 下载鸿蒙系统 下载地址&#xff1a;http…

MATLAB实现遗传算法优化第三类生产线平衡问题

第三类生产线平衡问题的数学模型 假设&#xff1a; 工作站数量&#xff08;m&#xff09;和生产线节拍&#xff08;CT&#xff09;是预设并固定的。每个任务&#xff08;或作业元素&#xff09;只能分配到一个工作站中。任务的执行顺序是预先确定的&#xff0c;且不可更改。每…

PHP医疗不良事件上报系统源码 AEMS开发工具vscode+ laravel8 医院安全(不良)事件报告系统源码 可提供演示

PHP医疗不良事件上报系统源码 AEMS开发工具vscode laravel8 医院安全&#xff08;不良&#xff09;事件报告系统源码 可提供演示 医院安全不良事件报告系统&#xff08;AEMS&#xff09;&#xff1b;分为外部报告系统和内部报告系统两类。内部报告系统主要以个人为报告单位&…

Docker私有镜像仓库搭建 带图形化界面的

搭建镜像仓库可以基于Docker官方提供的DockerRegistry来实现。 官网地址&#xff1a;https://hub.docker.com/_/registry 先配置私服的信任地址: # 打开要修改的文件 vi /etc/docker/daemon.json # 添加内容&#xff1a; "insecure-registries":["http://192.…

暴力匹配字符串的升级版算法 —— Kmp算法

文章目录 一、Kmp算法是什么&#xff1f;二、算法分析1.构建next数组2.匹配主串 三、完整代码 一、Kmp算法是什么&#xff1f; 简单来说&#xff0c;KMP&#xff08;Knuth-Morris-Pratt&#xff09;算法主要用于解决字符串匹配问题。也就是当你有一个主串&#xff08;text&…

OceanBase 轻量级数仓关键技术解读

码到三十五 &#xff1a; 个人主页 为了更好地聚合和治理跨域数据&#xff0c;帮助企业用较低的成本快速聚合分析&#xff0c;快速决策&#xff0c;不断的让企业积累的数据产生价值&#xff0c;从全域海量数据抓取&#xff0c;高性能流批处理&#xff0c;元数据血缘治理等等方面…

AI-数学-高中52-离散型随机变量概念及其分布列、两点分布

原作者视频&#xff1a;【随机变量】【一数辞典】2离散型随机变量及其分布列_哔哩哔哩_bilibili 离散型随机变量分布列&#xff1a;X表示离散型随机变量可能在取值&#xff0c;P:对应分布在概率&#xff0c;P括号里X1表示事件的名称。 示例&#xff1a;

QT:QT窗口(一)

文章目录 菜单栏创建菜单栏在菜单栏中添加菜单创建菜单项添加分割线 工具栏创建工具栏设置停靠位置创建工具栏的同时指定停靠位置使用QToolBar类提供的setAllowedAreas函数来设置停靠位置 设置浮动属性设置移动属性 状态栏状态栏的创建在状态栏中显示实时消息在状态栏中显示永久…

AI人才争夺战,华尔街入局:豪掷百万美元年薪抢人

继硅谷之后&#xff0c;华尔街也入局**“AI人才争夺大战”**。 他们的目标非常明确——抢的就是高精尖的AI专家。 △图源&#xff1a;Business Insider 现在这条“街”上&#xff0c;不论是银行、对冲基金还是私募股权公司都已纷纷下场&#xff0c;可谓是豪掷千金&#xff0c…

选择深度学习框架:TensorFlow 2 vs PyTorch

TensorFlow 2 vs PyTorch 选择深度学习框架&#xff1a;TensorFlow 2 vs PyTorchTensorFlow 2概述TensorFlow 2的优点TensorFlow 2的缺点 PyTorch概述PyTorch的优点PyTorch的缺点 选择建议对于选择困难症的人&#xff0c;我给你们的答案——PyTorch选择理由&#xff1a;结论&am…

【LinuxC语言】setitimer与getitimer函数

文章目录 前言一、setitimer() 函数二、getitimer() 函数三、示例代码总结 前言 在Linux系统下&#xff0c;编写程序时经常需要使用定时器来实现一些定时任务、超时处理等功能。setitimer() 和 getitimer() 函数是两个用于操作定时器的重要函数。它们可以帮助我们设置定时器的…