Linux系统编程 - 基础IO(IO操作)
目录
预备知识
复习C文件IO相关操作
printf相关函数
fprintf
snprintf
读取文件
系统文件IO操作
open函数
umask()函数
open函数返回值
预备知识
1.你真的理解文件原理和操作了吗?不是语言问题,是系统问题
2.是不是只有C/C++有文件操作呢? 不是,Java,python,go都有,他们的文件操作方法是不一样的?如何处理这种现象呢? 有没有一种统一的视角,看待所有的语言文件从操作呢?
3.操作文件的时候,第一件事情,就是打开文件,打开文件时做什么呢?如何理解呢?
4.文件 = 内容 + 属性 -> 针对文件的操作,对内容的操作,对属性的操作
5.当文件没有被操作的时候,文件一般会在什么位置? 磁盘!
6.当我们对文件进行操作的时候,文件需要在哪里? 内存,为什么呢? 因为CPU和内存交互
7.当我们对文件进行操作的时候,文件需要提前被load到内存,load是内容还是属性? 属性,因为一个文件至少得有属性
8.当我们对文件进行操作的时候,文件需要提前被load到内存,是不是只有你一个人在load呢?不是,内存中一定存在大量的不同文件的属性
9.所以综上,打开文件本质就是将需要的文件属性加载到内存中,OS内部一定会同时存在大量的被打开的文件,那么操作系统要不要管理这些被打开的文件呢? 要,OS需要先描述,在组织。
先描述,构建在内存中的文件结构体struct file{struct file* next},就可以从磁盘来,被打开的文件
a.每一个被打开的文件,都要在OS内对应文件对象的struct结构体,可以将所有的struct file结构体用某种数据结构链接起来--,在OS内部,对被打开的文件进行管理,就被转换成为了对链表的增删查改。
结论:文件被打开,OS要为被打开的文件,创建对应的内核数据结构
struct file
{
//各种属性
//各种链接关系
}
10.文件其实可以被分开两大类:磁盘文件,被打开的文件(内存文件)
11.文件被打开,是谁打开呢?OS,但是是谁让OS打开的呢?用户(进程为代表的)
12.我们之前的所有的文件操作,都是进程和被打开文件的关系
13.都是进程和被打开文件的关系:struct stak_struct和struct file
复习C文件IO相关操作
下面是用C语言实现对文件log.txt进行操作:
#include <stdio.h>
#define LOG "log.txt"int main()
{// w:默认写方式打开文件,如果文件不存在,就创建它// 默认如果只是打开,文件内容会自动被清空// 同时,每次进行写入的时候,都会从最开始进行写入FILE *fp = fopen(LOG, "w");if (fp == NULL){perror("fopen fail");return 1;}// 正常进行文件操作const char *msg = "hello linux\n";int cnt = 5;while (cnt){fputs(msg, fp);cnt--;}fclose(fp); // 关闭文件return 0;
}


成功创建了log.txt文件,打开文件

printf相关函数

printf 默认是向显示器读取
int main()
{// w:默认写方式打开文件,如果文件不存在,就创建它// 1. 默认如果只是打开,文件内容会自动被清空// 2. 同时,每次进行写入的时候,都会从最开始进行写入FILE *fp = fopen(LOG, "w");if (fp == NULL){perror("fopen fail");return 1;}// 正常进行文件操作const char *msg = "hello linux";int cnt = 5;while (cnt){fprintf(fp, "%s:%d:phw\n", msg, cnt);cnt--;}fclose(fp); // 关闭文件return 0;
}

fprintf
fprintf(stdout, "%s:%d:phw\n", msg, cnt); // Linux一切皆文件,stdout也对应一个文件,显示器文件

snprintf
写入到buffer缓冲里


下面测试一下将msg改成phw


这里得出结论, “w"为覆盖式写入
追加式写入"a"选项


读取文件



系统文件IO操作
open函数

pathname: 要打开或创建的目标文件
flags: 打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成flags。
参数:
O_RDONLY: 只读打开
O_WRONLY: 只写打开
O_RDWR : 读,写打开
这三个常量,必须指定一个且只能指定一个
O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限
O_APPEND: 追加写O_TRUNC:清空文件内容
返回值:
成功:新打开的文件描述符
失败:-1
下面是标志位的举例程序:
#define ONE 0x1
#define TWO 0x2
#define THREE 0x4
#define FOUR 0X8
#define FIVE 0X10void Print(int flags)
{if (flags & ONE)printf("hello 1\n");if (flags & TWO)printf("hello 2\n");if (flags & THREE)printf("hello 3\n");if (flags & FOUR)printf("hello 4\n");if (flags & FIVE)printf("hello 5\n");
}int main()
{printf("-------------------\n");printf(ONE);printf("-------------------\n");printf(TWO);printf("-------------------\n");printf(FOUR);printf("-------------------\n");printf(ONE | TWO);printf("-------------------\n");printf(ONE|TWO|THREE);printf("-------------------\n");printf(ONE|TWO|THREE|FOUR|FIVE);printf("-------------------\n");return 0;
}


open函数测试:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define LOG "log2/txt"// 系统方案
int main()
{int fd = open(LOG, O_WRONLY);printf("fd:%d\n", fd);return 0;
}

文件不存在
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#define LOG "log2/txt"// 系统方案
int main()
{int fd = open(LOG, O_WRONLY |O_CREAT);if (fd == -1){printf("fd:%d,errno:%d,errstring:%s\n", fd, errno, strerror(errno));}else{printf("fd:%d,errno:%d,errstring:%s\n", fd, errno, strerror(errno));}close(fd);return 0;
}
我们在使用open函数的时候不仅要O_WRONLY (写)还要创建O_CREAT
但是这种方式创建的文件,是没有权限的。

其中参数mode就是权限


因为umask默认权限的原因
umask()函数
umask() 函数的参数为一个八进制数,它的每一位分别表示对应的文件权限是否会被屏蔽掉,例如,umask(022) 表示屏蔽掉写入权限和执行权限。
umask(0)这意味着没有任何权限被屏蔽掉。

将mask初始化为0


成功将文件的权限设置成自己想要的
wirte()函数


这里的strlen不需要+1,\0是C语言的规定,不是文件的规定,\0会被解释成乱码
![]()
O_WRONLY | O_CREAT 默认不会对原始文件内容做清空,需要加上O_TRUNC
![]()
O_APPEND | O_CREAT 不会追加写,需要加上O_WRONLY
![]()
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#define LOG "log.txt"// 系统方案
int main()
{umask(0);int fd = open(LOG, O_RDONLY, 0666);if (fd == -1){printf("fd:%d,errno:%d,errstring:%s\n", fd, errno, strerror(errno));}else{printf("fd:%d,errno:%d,errstring:%s\n", fd, errno, strerror(errno));}char buffer[1024];// 这里无法做到按行读取,我们是整体读取的ssize_t n = read(fd, buffer, sizeof(buffer) - 1); //使用系统接口来进行IO的时候,一定要注意\0的问题if (n > 0){buffer[n] = '\0';printf("%s\n", buffer);}close(fd);return 0;
}

open函数返回值
在认识返回值之前,先来认识一下两个概念: 系统调用和库函数
上面的 fopen fclose fread fwrite 都是C标准库当中的函数,我们称之为库函数(libc)。
而, open close read write lseek 都属于系统提供的接口,称之为系统调用接口
回忆一下我们讲操作系统概念时,画的一张图

系统调用接口和库函数的关系,一目了然。 所以,可以认为,f系列的函数,都是对系统调用的封装,方便二次开发。
相关文章:
Linux系统编程 - 基础IO(IO操作)
目录 预备知识 复习C文件IO相关操作 printf相关函数 fprintf snprintf 读取文件 系统文件IO操作 open函数 umask()函数 open函数返回值 预备知识 1.你真的理解文件原理和操作了吗?不是语言问题,是系统问题2.是不是只有C/C有文件操作呢&#x…...
基于 Avue 的 CRUD 表格组件封装
在 components 文件夹中,创建一个新的 .vue 文件,例如:AvueCrudTable.vue。 透传父组件传递的属性和事件 : 1、利用v-bind=“ a t t r s " 支持所有 a v u e 的使用方法并在其基础上进行封装 2 、使用 v − o n = " attrs"支持所有 avue 的使用方法并在其基…...
树莓派学习笔记(十三)基于框架编写驱动代码
文章目录一、代码分析:二、源码一、代码分析: 在内核中由于代码文件多,避免函数名重复,使用static将函数的作用域限制在该文件内 内核的打印函数printk和printf类似 file_operations结构体使用符号“ . ”指定参数,省…...
vue事件修饰符之.prevent
.prevent 事件修饰符只是阻止默认事件,不会自动触发任何事件处理函数。因此,在使用 .prevent 事件修饰符时,需要自己编写相应的事件处理函数来处理事件。 例如,在上面的例子中,我们通过在表单上绑定 submit.prevent&q…...
【SpringCloud AlibabaSentinel实现熔断与限流】
本笔记内容为尚硅谷SpringCloud AlibabaSentinel部分 目录 一、Sentinel 1、官网 2、Sentinel是什么 3、下载 4、特性 5、使用 二、安装Sentinel控制台 1、sentinel组件由2部分构成 2、安装步骤 1.下载 2.运行命令 3.访问sentinel管理界面 三、初始化演示工程 …...
类与对象-封装
一、封装的意义封装是C面向对象三大特性之一语法: class name { 访问权限:属性行为 };注意:类中的属性和行为 统称为成员属性 又称 成员属性 / 成员变量行为 又称 成员函数 / 成员方法封装将属性和行为作为一个整体,表现生活中的事物例①&…...
【回忆杀】2012年拥有第一台电脑【致逝去的青春】
高中说起 在2012年的时候吧,高考过后,那个时候一门心思的想当一名体育老师【现在居然还有这个想法,哈哈】,最后没有考上自己希望的大学我记得好像是2012年7月的时候就去重庆投靠朋友,他教我做模具,2012年做…...
PointNeXt: Revisiting PointNet++ with Improved Training and Scaling Strategies
Abstract PointNet 是点云理解领域最有影响力的神经网络架构之一。虽然近期出现了 PointMLP 和 Point Transformer 等新型网络,它们的精度已经大大超过了 PointNet,但我们发现大部分性能提升是由于改进的训练策略,例如数据增强和优化技术以及…...
打印九九乘法表-课后程序(JavaScript前端开发案例教程-黑马程序员编著-第2章-课后作业)
【案例2-9】打印九九乘法表 一、案例描述 考核知识点 for双重循环 练习目标 掌握for循环应用。实现九九乘法表。 需求分析 九九乘法表相信大家一点也不陌生,之前见到的乘法表是印刷在课程本之上的。而在本案例中我们将用JavaScript代码来实现九九乘法表。 案例分…...
【Linux】基于阻塞队列的生产者消费者模型
🌠 作者:阿亮joy. 🎆专栏:《学会Linux》 🎇 座右铭:每个优秀的人都有一段沉默的时光,那段时光是付出了很多努力却得不到结果的日子,我们把它叫做扎根 目录👉为何要使用…...
【华为OD机试 2023最新 】 真正的密码(C++)
文章目录 题目描述输入描述输出描述用例题目解析C++题目描述 在一行中输入一个字符串数组,如果其中一个字符串的所有以索引0开头的子串在数组中都有,那么这个字符串就是潜在密码, 在所有潜在密码中最长的是真正的密码,如果有多个长度相同的真正的密码,那么取字典序最大的…...
差分算法(蓝桥杯复习+例题讲解+模板c++)
文章目录差分介绍差分应用区间加区间求和总结3729. 改变数组元素100. 增减序列文章首发于:My Blog 欢迎大佬们前来逛逛 差分介绍 差分是一种常见的算法,用于快速修改数组中某一段区间的值。 差分的思想就是预处理出数组的差分数组,然后修改…...
CSS+ JS 实现手电筒效果
前言概述 JavaScript 结合 CSS 打造的一款图片特效,当鼠标拖拽滑块时,让本该置灰的图片局部恢复本来的颜色。且该效果随着你的鼠标的按下时的移动而移动。 核心功能 图片置灰 拖拽功能 让滑块位置处的图片恢复本来的颜色 实现原理 这个的实现原理并不…...
2021地理设计组二等奖:基于InSAR和指数分析的地面沉降风
作品简介 一、作品背景 地面沉降是指地面高程的降低, 又称地面下沉或地沉, 是以缓慢、难以察觉的向下垂直运动为主, 是指在自然和人为因素作用下, 由于地壳表层土体压缩而导致区域性地面标高降低的一种环境现象。目前, 地面沉降己成为城市化进程中普遍存在的生态环境问题, 成为…...
计算机操作系统(第四版)第二章进程的描述与控制—课后习题答案
1.什么是前趋图?为什么要引入前趋图? 前趋图是一个有向无循环图,记为DAG,用于描述进程之间执行的先后关系。 2.试画出下面四条语句的前趋图: S1:axy; S2:bz1; S3:ca-b; S4:wc1; 3.为什么程序并发执行会产生间断性特征&…...
CAN通信----电路图
CAN通信----基本原理 一、CAN总线网络连接 1.闭环总线网络----ISO11898 闭环总线网络高速、短距离,它的总线最大长度为 40m,通信速度最高为 1Mbps,总线的两端各要求有一个120 欧的电阻。 2.开环总线网络----ISO11519 开环总线网络低速、…...
Windows系统安装ElasticSearch(一)
一 ES介绍Elasticsearch 是一个分布式可扩展的实时搜索和分析引擎,一个建立在全文搜索引擎 Apache Lucene(TM) 基础上的搜索引擎.当然 Elasticsearch 并不仅仅是 Lucene 那么简单,它不仅包括了全文搜索功能,还可以进行以下工作:分布式实时文件存储&#…...
linux 产生随机数 并遍历
1、产生随机数 varRANDOMvarRANDOM varRANDOMvar[ $var % 150 ] 2、产生不重复的随机数 $ entries($(shuf -i 0-149 -n 15)) $ echo “${entries[]}” 3、对随机数排序 $ entries($(shuf -i 0-149 -n 15 | sort -n)) $ echo “entries[]"12224549546678798393118119124140…...
【3.24】Mybatis常见面试题
Mybatis常见面试题 #{}和¥{}的区别是什么? 【#】:底层执行SQL使用PreparedStatement对象,预编译SQL,相对安全。入参使用占位符的方式。 【$】:底层执行SQL使用Statement对象,入参使用SQL拼接的…...
IDEA 热部署,修改代码不用重启项目
热部署指在修改项目代码的时候不重启服务器让修改生效。安装JRebel and XRebelFile->Settings,然后Plugins-> Marketplace,输入JRebel,安装如下插件——JRebel and XRebel ,重启idea激活JRebel and XRebel第一行输入网址&am…...
SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
