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

news2024/12/27 11:46:54

👀樊梓慕:个人主页

 🎥个人专栏:《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系列文章。 

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

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

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

🌟~ 点赞收藏+关注 ~🌟

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

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

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

相关文章

HCIP网络类型+串线+GRE

一.网络类型&#xff1a; 点到点 BMA&#xff1a;广播型多路访问 -- 在一个MA网络中同时存在广播&#xff08;泛洪&#xff09;机制 NBMA&#xff1a;非广播型多路访问 -- 在一个MA网络中&#xff0c;没有泛洪机制-----不怎么使用了 MA&#xff1a;多路访问 -- 在一个…

手机App防沉迷系统 - 华为OD统一考试

OD统一考试&#xff08;C卷&#xff09; 分值&#xff1a; 100分 题解&#xff1a; Java / Python / C 题目描述 智能手机方便了我们生活的同时&#xff0c;也侵占了我们不少的时间。“手机Ap防沉迷系统” 能够让我们每天合理的规划手机App使用时间&#xff0c;在正确的时间做…

Redis - redis.windows.conf配置文件及RDB和AOF数据持久化方案

Redis - redis.windows.conf配置文件及RDB和AOF数据持久化方案 Redis的高性能是由于其将所有数据都存储在了内存中&#xff0c;为了使Redis在重启之后仍能保证数据不丢失&#xff0c;需要将数据从内存中同步到硬盘中&#xff0c;这一过程就是持久化。 Redis支持两种方式的持久化…

Vue3 Suspense 优雅地处理异步组件加载

✨ 专栏介绍 在当今Web开发领域中&#xff0c;构建交互性强、可复用且易于维护的用户界面是至关重要的。而Vue.js作为一款现代化且流行的JavaScript框架&#xff0c;正是为了满足这些需求而诞生。它采用了MVVM架构模式&#xff0c;并通过数据驱动和组件化的方式&#xff0c;使…

[Linux]HTTP状态响应码和示例

1xx&#xff1a;信息响应类&#xff0c;表示接收到请求并且继续处理 2xx&#xff1a;处理成功响应类&#xff0c;表示动作被成功接收、理解和接受 3xx&#xff1a;重定向响应类&#xff0c;为了完成指定的动作&#xff0c;必须接受进一步处理 4xx&#xff1a;客户端错误&#x…

[笔记]Spring AOP

Spring AOP&#xff08;Aspect Oriented Programming&#xff09; AOP将应用程序分为核心业务和非核心的公共功能&#xff0c;AOP的关注点是系统中的非核心的公共功能&#xff1b; AOP可以通过预编译或者运行期动态代理的方式&#xff0c;为横跨多个对象&#xff08;没有继承关…

四、Flask学习之JavaScript

四、Flask学习之JavaScript JavaScript&#xff0c;作为一种前端脚本语言&#xff0c;赋予网页生动的交互性和动态性。通过它&#xff0c;开发者能够操作DOM&#xff08;文档对象模型&#xff09;实现页面元素的动态改变、响应用户事件&#xff0c;并借助AJAX技术实现异步数据…

omron adept控制器维修SmartController EX

欧姆龙机器人adept运动控制器维修SmartController EX 19300-000 维修范围&#xff1a;姆龙机器人&#xff1b;码垛机器人&#xff1b;搬运机器人&#xff1b;焊机机器人&#xff1b;变位机等。 Adept Viper s650/s850用于装配、物料搬运、包装和机械装卸&#xff0c;循环周期短…

基于YOLOv8深度学习的102种花卉智能识别系统【python源码+Pyqt5界面+数据集+训练代码】目标检测、深度学习实战

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

dom-to-image-more 使用

与网上不同的使用方式&#xff1a; 官网 dom-to-image-more - npm 这里不会出现两行缩略不行的bug yarn add dom-to-image-more 下面 生成图片并下载图片 const picture ref() const dom2img () > {var node picture.valuedomtoimage.toPng(node, { cacheBust: t…

iou的cpu和gpu源码实现

本专栏主要是深度学习/自动驾驶相关的源码实现,获取全套代码请参考 简介 IoU&#xff08;Intersection over Union&#xff09;是一种测量在特定数据集中检测相应物体准确度的一个标准&#xff0c;通常用于目标检测中预测框&#xff08;bounding box&#xff09;之间准确度的…

Arduino U8g2库:图形界面库的强大利器,

Arduino U8g2库&#xff1a;图形界面库的强大利器 介绍 在Arduino世界中&#xff0c;图形界面的显示通常是一项关键的任务。为了简化这个过程&#xff0c;提高开发效率&#xff0c;许多库被开发出来&#xff0c;其中U8g2库就是其中之一。U8g2库是一个功能强大的图形库&#x…

uniapp复选框 实现排他选项

选择了排他选项之后 复选框其他选项不可以选择 <view class"reportData" v-for"(val, index) in obj" :key"index"> <view v-if"val.type 3" ><u-checkbox-group v-model"optionValue" placement"colu…

web系统服务器监控检查

一、检查操作系统是否存在增减文件&#xff0c;是否有shell被上传 要检查操作系统是否存在增减文件或是否有shell被上传&#xff0c;您可以按照以下步骤进行操作&#xff1a; 文件完整性检查&#xff1a; 使用文件系统的完整性检查工具&#xff0c;例如fsck&#xff08;对于ext…

项目一:踏上Java开发之旅

文章目录 一、实战概述二、实战步骤任务1&#xff1a;安装配置JDK并开发第一个Java程序步骤一&#xff1a;安装JDK步骤二&#xff1a;配置JDK环境变量步骤三&#xff1a;开发第一个Java程序 课堂练习任务1、打印个人信息任务2、打印直角三角形任务3、打印一颗爱心任务4、打印史…

git:使用git rebase合并多次commit为一个

git log&#xff1a;找到需要合并的最早 commit 的父级 git rebase -i 73a5cd8597除第一个 pick 外&#xff0c;将其它改成 s&#xff0c;改完后保存退出 保存完后弹出 commit message 合并提示&#xff0c;根据这次合并的目的&#xff0c;重写commit message&#xff0c;改完后…

软考复习之软件工程篇

软件生命周期 问题定义&#xff1a;要示系统分析员与用户进行交流&#xff0c;弄清”用户需要计算机解决什么问题”然后提出关于“系统目标与范围的说明”&#xff0c;提交用户审查和确认 可行性研究&#xff1a;一方面在于把待开发的系统的目标以明确的语言描述出来&#xf…

httpClient忽略https的证书认证

忽略https证书认证代码: /*** 创建模拟客户端&#xff08;针对 https 客户端禁用 SSL 验证&#xff09;* return* throws Exception*/public static CloseableHttpClient createHttpClientWithNoSsl() throws Exception {// Create a trust manager that does not validate cer…

【C++】初步认识基于C的优化

C祖师爷在使用C语言时感觉到了不方便的一些点&#xff0c;于是一步一步改进优化&#xff0c;最后形成了C 本文将盘点一下基于C的语法优化 目录 命名空间&#xff1a;命名空间定义&#xff1a;命名空间使用&#xff1a; C输入&输出&#xff1a;cout&#xff1a;endl&#…

司铭宇老师:门店服装销售技巧培训:卖衣服销售方法和技巧

门店服装销售技巧培训&#xff1a;卖衣服销售方法和技巧 在服装零售行业&#xff0c;销售方法和技巧对于提升销售业绩和增强顾客满意度至关重要。一个成功的销售人员需要掌握如何吸引顾客、如何展示商品、如何促成交易等多方面的技能。以下是关于卖衣服的销售方法和技巧的详细…