Linux中文件操作

文件由文件内容和文件属性构成,因此对文件的操作就是对文件内容或文件属性的操作。所谓的“打开一个文件”就是将文件的属性或内容加载到内存中,而没有被打开的文件存在于磁盘上。打开的文件称作“内存文件”,未被打开的文件称作“磁盘文件”。当我们使用一系列文件函数(fopen,fread等)访问文件时,其本质是这些文件程序转换成可执行程序,运行起来后执行对应的代码才是对文件的一系列操作,其实就是进程对文件进行操作。


系统调用和库函数:

open函数 

open函数用于打开或创建一个文件的系统调用。

flags有五个选项(严格来说不知五个,目前只了解五个)

  1. O_RDONLY:以只读的方式打开文件;
  2. O_WRONLY:以只写的方式打开文件;
  3. O_RDWR:以读写的方式打开文件;
  4. O_CREAT:如果文件不存在则创建文件;
  5. O_TRUNC:如果文件已经存在且为只写或读写,则将其长度截断为0;(即清空文件内容)

close函数

int close(int fd);

fd表示要关闭的文件的描述符,是一个非负整数,通常由open等系统调用获得,成功时返回0,出错返回-1。


write函数

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

 fd表示文件描述符,通常由open这一类系统调用获得,buf表示要写入文件的数据缓冲区指针,count表示要写入缓冲区的字节数,成功时返回写入的字节数,失败时返回-1,并通过errno显示错误类型。


read函数

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

count表示要读取的最大字节数。read函数将fd文件中的内容读取到buf中。成功时,read返回实际读取的字节数,失败时返回-1,通过errno显示错误信息。read系统调用不会因为'\0'而停止读取,他会一直读取到buf数组的最大值后结束。


open打开不存在文件的权限

使用open函数打开一个不存在的文件时不能使用第一个类型的参数列表,此时创建出来的文件权限存在一个s权限,该权限表示强制位权限,易造成系统安全问题。因此在打开一个不存在文件时要使用第二个参数列表。但是即使我将文件权限设置为777时,按理来说此时文件权限应为"-rwx rwx rwx",但是别忘记文件权限还与umask码有关。默认umask为002,新创建的文件权限结果计算方法为:文件权限&(~umask)。

通过修改umask的值使得创建的文件t1.txt的权限为"-rwx rwx rwx"。

C语言中"w"的底层逻辑

如上图,继续在已经有内容的文件中写入数据,是一种覆盖式的写入,如何做到清空原有数据内容,重新写入数据呢?

将打开文件方式设为"O_TRUNC",表示当文件已经存在时会将其长度截断,也就是清空其内容,这也是C语言函数中fopen("filename","w")的底层逻辑

c语言中"a"的底层逻辑

多次运行./a.out,数据以追加的形式写入到t1.txt文件中,这也是c语言中fopen("t1.txt","a")实现的底层逻辑。

文件描述符

为什么文件描述符从3开始?

验证0.1.2就是标准IO

验证0.1.2对应的就是stdin,stdout,stderr

因为stdin,stdout以及stderr是FILE*类型的指针,而FILE结构体内部封装了_fileno用于存放该FILE指针关联的文件描述符,通过访问_fileno就可以获得其对应的文件描述符。


进程与文件的关系

文件在内存中被打开,一个进程又可以打开多个文件,OS如何对打开的文件进行管理呢。OS通过先描述,再组织的方式,通过构建结构体struct file使各个文件之间通过struct file*指针的方式(类似链表)使各个文件之间建立关系。我们知道进程一旦被创建就会有PCB,也就是task_struct,这个结构体里面就含有struct files_struct* files,其指向的是struct files_struct。在struct files_struct中有含有一个struct file* fd_arr[]数组,该数组专门存放struct file*类型的指针,也就是指向的文件地址即struct file(该结构体内存放各种文件属性)。

那么0、1、2对应的是stdin、stdout、stderr其对应的又是键盘、显示器,如何将这些硬件使用文件描述符对应的呢?

理解这个问题先理解“Linux下一切皆文件”:尽管在计算机中有许多硬件(如硬盘、显示器、网卡等),但是OS仍然能通过类似文件的读写方法对这些硬件进行使用、访问等操作。OS会创建不同的struct file,这其中就包含各种对硬件的读写方法函数指针,OS通过这些函数指针找到函数然后对硬件进行访问。

文件描述符的分配规则

如上图所示,文件描述符会按照数组中最小的空下标进行分配。


重定向的使用

如上图所示,当将数组下标为1的文件描述符指向的内容关闭后(也就是关闭stdout),那么此时ret的值就为1(参考文件描述符的分配规则),此时运行编译后的文件时,write函数直接将内容写到ret指向的文件中,而不会再将“Hello linux”显示在输出设备(因为1对应的是stdout,即显示器)上,而是显示在此时对应的数组中1指向的内容中去(也就是T1.txt文件中)。这就是“重定向”。

使用系统接口实现重定向:这里需要用到dup2函数int dup2(int oldfd, int newfd);该函数用于文件描述符的重定向,其头文件是<unistd.h>,该函数允许将文件描述符newfd重定向到另一个文件描述符oldfd(源文件描述符,也就是要进行重定向的文件描述符),newfd表示目标文件描述符。函数调用成功返回新文件的描述符,失败返回-1,并可以以perror显示错误类型。

重定向使用演示

如上图,第一次演示时,write函数直接将str数据写到了文件描述符1上(也就是显示器),此时虽然创建了T4.txt,但是该文件中没有内容。第二次演示时,通过dup2函数将文件描述符1改为ret(因为dup2(oldfd,newfd),new是old的一份拷贝,也就是说old的值给了new,并且new会被关闭,此时old文件描述符是new),因此这里1已经被改为ret(也就是T4.txt)。所以再次write时就会写到T4.txt文件中。

如上图,对T4.txt进行追加内容的操作,在第二次演示中,通过read函数从0(对用的就是stdin,键盘)中读取数据,并将数据写到str(注意:代码第23行中,read函数第三个参数有误,)。第三次演示中,重定向文件描述符0为ret,也就是T4.txt,此时fgets函数就从T4.txt文件中获取数据。


缓冲区的概念

缓冲区存在的意义在于解放使用缓冲区的进程的时间(例如啊当一个进程要打印数据在显示器上时,进程会将数据放入缓冲区,之后该进程就去执行自己的代码了),并且缓冲区可以集中数据刷新,减少IO次数,从而提高整机的效率。

在左边代码中printf通过\n刷新缓冲区,内容会立即被刷新到显示器中。在右边代码中,printf没有\n刷新缓冲区,因此数据不会立即被刷新。而write函数又是立即刷新的,printf函数又封装了write函数,那么write函数的缓冲区在哪里?首先肯定的是write函数的缓冲区一定不在wirte函数内部,如果write函数缓冲区在write函数内部,那么printf函数即使没有\n也应该立即刷新缓冲区(因为printf函数封装了write函数,而write函数又是立即刷新缓冲区的),显然右边代码演示就否定的这一判断。其实write函数的缓冲区由C语言提供的,是一种语言级别的缓冲区。因此在C语言中每次打开一个文件时,都会有一个FILE*返回(fopen函数),每一个文件都有一个fd和一个属于他自己的语言缓冲区。

在printf(包括fprintf,fputs等函数)中都显示或隐式的包含stdout,而stdout又是FILE*类型的,而FILE是一个结构体,其内部包含各种属性,其中包含fd以及FILE对应的语言级别的缓冲区,也就是说FILE内部封装了自己的缓冲区。因此当printf打印数据时,此时数据会被先存储到stdout对应的缓冲区中,当数据达到缓冲区的容量时,此时OS就会刷新缓冲区,将数据写到硬件上,从而达到减少IO次数,提高整机效率,减少进程使用缓冲区的时间。

那么缓冲区什么时候刷新一次合适呢(也就是刷新策略)?如果缓冲区还没刷新但是关闭了文件描述符?

刷新策略:

  1. 行缓冲:逐行刷新
  2. 全缓冲:缓冲区满才刷新,(磁盘)
  3. 无缓冲:立即刷新
  4. 强制刷新:fflush
  5. 进程退出。

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

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

相关文章

hhdb数据库介绍(10-42)

安全 SQL防火墙 管理平台提供的SQL防火墙功能可为用户拦截高危SQL、误操作SQL等&#xff0c;提升系统安全性。 同时防火墙提供观测功能&#xff0c;可在开启新规则前&#xff0c;通过开启观测状态&#xff0c;判断新规则对业务的影响程度。开启观测状态后&#xff0c;计算节…

白嫖VMware ESXi 8.0 U3新功能Live Patch、无需重启零中断修复漏洞

哈喽大家好&#xff0c;欢迎来到虚拟化时代君&#xff08;XNHCYL&#xff09;&#xff0c;收不到通知请将我点击星标&#xff01;“ 大家好&#xff0c;我是虚拟化时代君&#xff0c;一位潜心于互联网的技术宅男。这里每天为你分享各种你感兴趣的技术、教程、软件、资源、福利…

JavaSE学习心得(API与算法篇)

常用API和常见算法 前言 常用API Math System Runtime Object ​编辑浅克隆 深克隆 Objects Biginteger 构造方法 成员方法 底层存储方式 Bigdecimal 构造方法 Bigdecimal的使用 底层存储方式 ​编辑正则表达式 两个判断练习 两个爬取练习 贪婪爬取和非贪…

如何开发高效的企业内训APP?教育培训系统源码搭建实战详解

本篇文章&#xff0c;小编将从教育培训系统的源码搭建、功能设计以及技术实现等方面&#xff0c;详细探讨如何开发一款高效的企业内训APP。 一、企业内训APP的需求分析 在开发企业内训APP之前&#xff0c;首先需要明确其基本需求。一个高效的企业内训APP应该具备以下几个核心…

解释器模式的理解和实践

引言 解释器模式&#xff08;Interpreter Pattern&#xff09;是一种行为型设计模式&#xff0c;它在软件工程中用得相对较少&#xff0c;但在某些特定场景下非常有用。解释器模式提供了一种解释语言的语法或表达式的方式&#xff0c;它定义了一个表达式接口&#xff0c;并通过…

Z029 PHP+MYSQL+LW+饭店预订管理系统的设计与实现 源代码 配置 文档

饭店预订管理系统 1.项目描述2. 开发背景与意义3.项目功能结构4.界面展示5.源码获取 1.项目描述 近几年来&#xff0c;我国计算机信息技术发展迅速&#xff0c;各种各样的信息管理系统层出不穷。互联网电子商务的热潮&#xff0c;改变了人们生活习惯&#xff0c;而作为城市经济…

【力扣热题100】—— Day5.回文链表

正视自己的懦弱和无能&#xff0c;克服自己的嫉妒与不甘 —— 24.12.3 234. 回文链表 给你一个单链表的头节点 head &#xff0c;请你判断该链表是否为 回文链表 。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输入&#xff1a…

什么是大数据、有什么用以及学习内容

目录 1.什么是大数据&#xff1f; 1.1大数据的类型 1.2大数据的来源 1.3大数据处理的挑战 1.4大数据的核心技术 2.大数据有什么用&#xff1f; 2.1商业与营销&#xff1a; 2.2医疗与健康&#xff1a; 2.3金融服务&#xff1a; 2.4政府与公共服务&#xff1a; 2.5交通…

Docker 安装 中文版 GitLab

Docker 安装系列 安装GitLab、解决服务器内存不足问题、使用域名/IP地址访问项目 1、拉取 [rootTseng ~]# docker pull twang2218/gitlab-ce-zh:latest latest: Pulling from twang2218/gitlab-ce-zh 8ee29e426c26: Pull complete 6e83b260b73b: Pull complete e26b65fd11…

分布式数据库环境(HBase分布式数据库)的搭建与配置

分布式数据库环境&#xff08;HBase分布式数据库&#xff09;的搭建与配置 1. VMWare安装CentOS7.9.20091.1 下载 CentOS7.9.2009 映像文件1.2启动 VMware WorkstationPro&#xff0c;点击“创建新的虚拟机”1.3在新建虚拟机向导界面选择“典型&#xff08;推荐&#xff09;”1…

ssh连接工具

我们未来接触到的linux系统一般情况下是没有界面&#xff08;桌面环境&#xff09;&#xff0c;我们一般会在自己工作的电脑上&#xff0c;通过相关ssh工具&#xff0c;利用网络连接到远程的你的服务器上。连接工具有很多&#xff1a;mobaxterm、xshell/xftp、putty等等 mobaxt…

苹果 ATS 配置SSL证书

Apple的App Transport Security (ATS) 是一项安全机制&#xff0c;旨在确保iOS和macOS应用的网络通信使用HTTPS加密。自iOS 9和OS X 10.11以来&#xff0c;默认情况下所有网络请求都必须使用HTTPS&#xff0c;除非明确允许非HTTPS连接。 在2017年1月1日之前&#xff0c;开发者可…

安卓逆向之对抗Anti-Frida学习

基础补充 什么是 Anti-Frida 保护&#xff1f; Anti-Frida保护是指在移动应用或程序中采用的一种安全技术或防护机制&#xff0c;旨在防止或干扰Frida等动态分析工具的注入与使用。 Anti-Frida保护常见技术 有哪些&#xff1f; 检测frida-agent.so的注入 &#xff1a; Fr…

安全架构评审

安全架构评审 1.概述2.安全设计原则3.美团安全架构评审模型安全需求分析架构review攻击面分析和威胁建模攻击面分析威胁列表 1.概述 完整的安全评审会包含安全架构评审、安全代码审核和安全测试三个手段 安全架构评审聚焦于探寻安全设计中的漏洞&#xff0c;以宏观视野全面考…

迎接国庆,我上线了第一款小程序

最近花了些时间&#xff0c;写了一个 “国庆头像” 小程序。正好快国庆节了&#xff0c;于是分享一下我的这个 “Starstick星点贴纸” 小程序&#xff0c;顺便简单讲讲以及其中的设计、开发、上线过程。 小程序的界面是这样的&#xff1a; &#x1f52e;背景 今年中秋前夕&am…

房产销售系统

文末获取源码和万字论文&#xff0c;制作不易&#xff0c;感谢点赞支持。 摘 要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于房产销售系统当然也不能排除在外&#xff0c;随着网络技术的不…

开发一套ERP 第二个生产版本

库存管理第一个生产版本 Okay 进入测试 嘿嘿,搞完了,剩下的就是细测慢调了 下一版本可以内置sqlite 数据库来操作这些数据表,sqlite 也支持 trigger 的功能

Weiss 机器人电动夹爪,重塑工业自动化精密操作

在当今的自动化进程里&#xff0c;Weiss高精密电动夹爪扮演着重要的角色。Weiss公司位于德国&#xff0c;其精心研制的高精密电动夹爪专为工业机器人与协作机器人打造。 Weiss 高精密电动夹爪的控制方式独具特色&#xff0c;与传统的一些夹爪相比&#xff0c;Weiss电动夹爪在处…

【JVM虚拟机】面试经典八股文(应届生必看)

目录 1.JDK、JRE、JVM三者关系&#xff1f; 2.谈谈JVM的理解&#xff1f; 3.JVM执行字节码的过程&#xff1f;&#xff08;执行方式&#xff09; 4.JVM的组成是什么&#xff1f; 5.什么是类加载机制&#xff1f; 6.什么是双亲委派模型&#xff1f; 7.JVM内存模型 8.堆区的…

Android 实现中英文切换

在开发海外项目的时候&#xff0c;需要实现app内部的中英文切换功能&#xff0c;所有的英文都是内置的&#xff0c;整体思路为&#xff1a; 创建一个sp对象&#xff0c;存储当前系统的语言类型&#xff0c;然后在BaseActivity中对语言进行判断&#xff1b; //公共Activitypubl…