Linux基础IO(二)

news2024/11/27 4:03:25

Linux基础IO(二)

文章目录

      • Linux基础IO(二)
        • 缓冲区
          • 为什么会有缓冲区
          • 缓冲区刷新策略
          • 系统有缓冲区吗?
        • 文件系统
          • 什么是inode
        • 软硬链接
          • 软链接
          • 硬链接
          • 热知识
          • 总结
        • 文件的三个时间
        • 动静态库
          • 什么是动静态库
          • 怎么理解动静态库
            • 原理
            • 使用
          • 制作一个库
            • 前置准备
            • 自制静态库
            • 使用自制的静态库
            • 自制动态库
            • 使用自制的动态库

缓冲区

为什么会有缓冲区

其实缓冲区的意义是节省进程进行数据 IO 的时间

怎么理解呢?我来举个例子:

孩子上大学了,学校里的水果又很贵,孩子给家里人说了,家里人知道了要给孩子每隔一段时间送点水果。下面有两个选项:

  • 1.亲自开车给孩子送
  • 2.发快递

相信大家大部分人会选择发快递吧,这样既省时间,又省事。

当然操作系统也是这样做的,它也有自己的缓冲区。当我们刷新用户缓冲区的数据时,并不是直接将数据直接刷新到磁盘或显示器上,而是先刷新到OS缓冲区,然后由操作系统将数据刷新到磁盘或者显示器。

缓冲区刷新策略
  • 无缓冲:缓冲区一出现数据,立即刷新

  • 行缓冲:缓冲区每出现一行数据就刷新一次

  • 全缓冲:缓冲区被填满后再刷新

还有两种方式强制刷新缓冲区:

  • fflush()等函数
  • 进程退出

为什么会有缓冲区刷新策略呢?

因为操作系统要求的是高效:一次写入外设等设备的时间消耗是远小于多次写入外设的效率的。其中时间消耗大部分是在等待外设就绪,例如缓冲区等待磁盘的时间就远小于缓冲区数据写入磁盘的时间,比如10秒时间内。9秒的时间是在等磁盘准备就绪,1秒是在写入数据。

操作系统可是个聪明人,它可不会傻傻的浪费自己宝贵的时间。

我们通过一段代码来加对深缓冲策略的理解:

int main()
{
    printf("aaaaaaaaaaaaaa\n");
    fputs("bbbbbbbbbbbbbb\n", stdout);

    write(1, "xxxxxxxxxxxxxx\n", 14);

    fork();
    return 0;
}

在我们直接运行程序时:

image-20230726102120541

但是当我们重定向进文件时:

image-20230726102205197

  • 第一种情况是行缓冲,我们每使用的\n都是行缓冲。
  • 第二种情况是全缓冲,因为我们把程序重定向到一个文件中,文件是全缓冲,又因为我们使用fork创建了一个子进程,而进程间互不干扰,所以都会打印一次字母a和字母b。而字母x是系统调用write,我们可以看作系统是没有缓冲区的(其实有,只是我们并不清楚规则)所以只打印一次。
系统有缓冲区吗?

用户写入数据到外设,先将数据写入系统缓冲区,再由系统刷新到外设中。

image-20230726103640596

因为操作系统是进行软硬件资源管理的软件,再加上我们之前学过的层级结构图(具体细节请看我之前写过的初识操作系统的文章),用户区的数据要刷新到具体外设必须经过操作系统,所以操作系统是肯定有自己的缓冲区的。

image-20230726103318600

文件系统

文件分为磁盘文件和内存文件,我们之前一直说的都是内存文件,下面我们来谈谈磁盘文件。

什么是inode

我们都知道文件=内容+属性,其中内容就是数据,属性就是文件名、创建日期和文件大小等。

我们输入ll命令可以查看当前路径下的文件:

image-20230726104854592

文件属性是这样的:

image-20230726110211704

我们还可以查看这些文件的inode

[wsj@VM-8-4-centos day03]$ ll -i
//或者
[wsj@VM-8-4-centos day03]$ ls -i -l

image-20230726110400049

inode到底是什么呢?

inode是一个保存元信息的结构,且因为系统中有大量的文件,为了区分每个文件,就给每个文件一个inode号,这个inode号就和我们每个人有自己的身份证号一样。

所以说inode是一个文件属性的集合。

软硬链接

软链接

我们可以通过以下命令创建一个软链接:

[---@VM-8-4-centos day03]$ ln -s mycode a_mycode

image-20230726114456471

我们通过ls -l -i可以看到软链接的文件和源文件的inode是不同的,而且文件大小也是差异很大的。

image-20230726123353422

软链接又叫做符号链接,软链接文件相对于源文件来说是一个独立的文件,它有自己的inode号,但是该文件只包含了源文件的路径名,所以软链接文件的大小要比源文件小得多。

其实软链接就类似于Windows操作系统当中的快捷方式。

所以说,运行源文件和运行快捷方式(软链接)是一样的结果。

image-20230726114855483

硬链接
[---@VM-8-4-centos day03]$ ln mycode b_mycode

image-20230726123625078

我们通过ls -l -i可以看到软=硬链接的文件和源文件的inode是相同的,而且文件大小差不多一模一样,硬链接个数也从1变成了2。

image-20230726123711402

硬连接其实就是文件的一个别名,硬链接个数就是文件别名的个数。

和软连接相比,硬链接的源文件被删除后,硬链接仍然可以执行。

image-20230726130658800

硬链接可以让多个不在或者同在一个目录下,能够修改同一个文件,且其中一个修改后,所有与其有硬链接的文件都一起修改了。

热知识

当我们创建一个普通文件时,他的硬链接是1,而我们创建一个目录文件他的硬链接是2,这是为什么?

image-20230726131129812

原因是该dir目录下必须有有两个隐藏文件...。它们分别是上级目录和当前目录,这就是我们常看别人用的cd ..的原理。(inode也是相同的)

image-20230726131349218

总结
  1. 软链接有独立的inode,硬链接没有。
  2. 软链接不能独立运行,硬链接能独立运行。
  3. 软链接相当于快捷方式,硬链接本质没有创建文件,只是对当前文件的复制加上对原来inode的映射,并写入当前目录。

文件的三个时间

  • Access:最后访问时间
  • Modify:文件最后修改时间
  • Change:属性最后修改时间
[---@VM-8-4-centos day03]$ stat day03.cc

image-20230726132046896

一般来说,Modify改变会引起Change一起变。因为修改文件内容时,文件的大小一般也会随之改变。但是Change改变却不会引起Modify改变,因为修改文件属性一般不会影响到文件内容。

使用touch命令可以将文件都更新为最新时间。

image-20230726132457483

动静态库

什么是动静态库
  • 动态库:程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。(*.so)
  • 静态库:程序在编译链接的时候把库的代码链接 (拷贝) 到可执行文件中,程序运行的时候将不再需要静态库。(*.a)
怎么理解动静态库
原理

生成一个可执行程序需要经过:预处理、编译、汇编、链接,4个阶段。

最终在汇编完成后就会*.o文件,将这样的经常使用的多个*.o文件组合起来就是一个简单的库。因为当需要使用到这个库中的哪个*.o文件,我们直接进行最后一步链接就行,省去了前3个步骤。

实际上,库都是这样做的。把常用的头文件或者函数调用汇编后组合成一个库,以供大家方便使用。

使用

我们可以通过以下命令查看可执行文件链接的库:

[---@VM-8-4-centos day03]$ ldd mycode

image-20230726192053739

我们可以通过ls命令查看libc.so.6库的情况:

[wsj@VM-8-4-centos day03]$ ls /lib64/libc.so.6 -l

image-20230726192431520

我们还可以通过以下命令来查看这个库的详细信息:

[---@VM-8-4-centos day03]$ file /lib64/libc-2.17.so

image-20230726193221821

我们可以看到这是一个动态库,而且还是一个共享的目标文件库。

我们使用的gcc/g++都是动态链接的,如果想要静态链接,我们要在编译时加上-static

我这边直接加在makefile里:

image-20230726193501575

这样我们make生成的就是静态链接的可执行程序了。

image-20230726193632679

这可比我们之前生成的动态链接的可执行程序大多了,但是它不依赖其他的库。

image-20230726193752743

我们再使用file命令,也能看出它是一个静态链接的可执行程序。

image-20230726193838320

制作一个库
前置准备

add.h

#pragma once

#include <stdio.h>

extern int add(int x, int y);

add.c

#pragma once
#include "add.h"
int add(int x, int y)
{
    return x + y;
}

sub.h

#pragma once

#include <stdio.h>

extern int sub(int x, int y);

sub.c

#pragma once
#include "sub.h"

int sub(int x, int y)
{
    return x - y;
}

main.c

#include "add.h"
#include "sub.h"

int main()
{
    int a = 10, b = 20;
    int c = add(a, b);
    int d = sub(a, b);
    printf("%d + %d = %d\n", a, b, c);
    printf("%d - %d = %d\n", a, b, d);
    return 0;
}
自制静态库

首先,我们将它们汇编为可重定向二进制目标文件:

gcc -c *.c -o *.o

image-20230726202442985

然后,我们使用以下命令将目标文件打包为静态库:

  • ar命令是gnu的归档工具,常用于打包静态库
  • -r:如果静态库文件当中的目标文件有更新,就用新的目标文件替换旧的目标文件。
  • -c:生成静态库文件。
  • -t:列出静态库中的文件。
  • -v:显示详细的信息。
[---@VM-8-4-centos day03]$ ar -rc liblocal.a add.o sub.o

image-20230726215514781

我们可以使用-v-t选项查看生成的静态库的详细信息:

[wsj@VM-8-4-centos day03]$ ar -vt liblocal.a

image-20230726215540429

最后,将头文件和生成的静态库联系起来。

[---@VM-8-4-centos day03]$ mkdir -p mymathlib/include
[---@VM-8-4-centos day03]$ mkdir -p mymathlib/lib
[---@VM-8-4-centos day03]$ cp *.h mymathlib/include/
[---@VM-8-4-centos day03]$ cp liblocal.a mymathlib/lib/

image-20230726215705688

使用自制的静态库

main.cmymathlib移动到一个新的目录下。

image-20230726204419374

使用gcc的选项-I-L生成可执行程序。

  • -I:指定头文件路径
  • -L:指定库文件路径
  • -l:指定路径下的哪一个库
[---@VM-8-4-centos day04]$ gcc -o mycode main.c -I ./mymathlib/include -L ./mymathlib/lib -l local

image-20230726215759737

然后,我们正常运行即可。

image-20230726215846754

我们也可以将我们的库拷贝到系统目录下,这样系统就可以找到我们使用的库,我们就不用指定路径了:

[---@VM-8-4-centos day04]$ sudo cp mymathlib/include/* /usr/include/
[---@VM-8-4-centos day04]$ sudo cp mymathlib/lib/liblocal.a /lib64/

image-20230726220357941

自制动态库

首先生成*.o文件。

  • -fPIC:形成位置无关码
[---@VM-8-4-centos day03]$ gcc -fPIC -c add.c sub.c

image-20230726220929255

然后,使用-shared选项打包目标文件为库。

image-20230726221200779

最后,将头文件和库联系起来。

[---@VM-8-4-centos day03]$ mkdir -p mymathlib/include
[---@VM-8-4-centos day03]$ mkdir -p mymathlib/lib
[---@VM-8-4-centos day03]$ cp *.h mymathlib/include/
[---@VM-8-4-centos day03]$ cp liblocal.so mymathlib/lib/

image-20230726221653951

image-20230726221753391

使用自制的动态库

main.cmymathlib移动到同一个目录下。

使用以下命令(和刚才使用静态库基本一样):

[wsj@VM-8-4-centos day04]$ gcc -o mycode main.c -I ./mymathlib/include -L ./mymathlib/lib -l local

image-20230726222304123

我们此刻执行后却是无法运行。

image-20230726222348403

原因是生成的可执行程序依赖的动态库没有被找到。

image-20230726222500538

解决方法:

方法1:将动态库拷贝到系统目录下。

sudo cp mymathlib/lib/liblocal.so /lib64

方法2:添加环境变量

[---@VM-8-4-centos day04]$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/wsj/bit/day04/mymathlib/lib

image-20230726223008615

方法3:配置/etc/ld.so.conf.d/

[---@VM-8-4-centos day04]$ echo /home/wsj/bit/day04/mymathlib/lib > matH.conf
[---@VM-8-4-centos day04]$ sudo cp matH.conf /etc/ld.so.conf.d

image-20230726223418618

完成任意一种解决方法后运行即可。

image-20230726223546931

感谢您的阅读,欢迎指正。

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

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

相关文章

根据索引值计算item所在行列索引序号

getRowColIndex(itemIndex 0, colCount 3) {//必选参数&#xff1a;itemIndex是当前元素的索引值&#xff0c;从0开始计算&#xff08;如果是从1开始&#xff0c;则需将传入值-1&#xff0c;即itemIndex--&#xff09;//必选参数&#xff1a;colCount是每一行显示多少个元素r…

使用Anaconda创建虚拟环境并添加到Jupyter notebook内核

1.修改虚拟环境的存放位置&#xff08;可选&#xff09; Windows&#xff1a;打开文件C:\Users\DongZhaoCheng(对应到你本人的用户名)\.condarc,添加envs_dirs: [D:\003SoftDevTool\anaconda_env]&#xff08;对应到你自己执行的目录&#xff09;,保存退出 2.进入系统终端创建…

Windows 11隐藏功能大揭秘

Windows 11隐藏功能大揭秘&#xff01;你了解多少&#xff1f; 不知道你是否已经升级到了Windows 11系统&#xff1f;毕竟&#xff0c;这个备受期待的新系统已经发布有一段时间了&#xff0c;相信大多数用户都已经开始尝试使用微软的新系统了吧。但是&#xff0c;你真的熟悉它…

查看进程环境变量

1、Linux 每一个进程的环境变量存储在 /proc/$PID/environ 中。 而 PID 可用通过 ps / jps(java 进程) 等命令查看。 ps -ef | grep xxxjps文件 /proc/$PID/environ 变量以namevalue的形式描述。多个变量之间由 null&#xff08;‘\0’&#xff09;分隔&#xff0c;为了便于阅…

嵌入式和 Java 走哪条路?

JAVA和嵌入式各有千秋&#xff0c;看个人取舍。 想挣钱挣得快一点&#xff0c;挣得多一点&#xff0c;那就选Java&#xff0c;但有中年危机。 想细水长流一点的&#xff0c;选嵌入式&#xff0c;挣钱挣得慢一点&#xff0c;也稳一点&#xff0c;挣得久一点&#xff0c;中年危…

Beamer学习手册

Beamer学习手册 ZJU Beamer模板解读参考链接 谨以本文记录一下学习beamer的过程 本文基于 Overleaf 的 ZJU Beamer模板 进行学习并修改模板&#xff0c;感谢前辈的贡献&#xff01; ZJU Beamer模板解读 首先在 Overleaf 下载 ZJU Beamer模板 &#xff0c;解压压缩包后&#xf…

Docker网络与Docker Compose服务编排

docker网络 docker是以镜像一层一层构建的&#xff0c;而基础镜像是linux内核&#xff0c;因此docker之间也需要通讯&#xff0c;那么就需要有自己的网络。就像windows都有自己的内网地址一样&#xff0c;每个docker容器也是有自己的私有地址的。 docker inspect [docker_ID]…

064、故障处理之OMM_TiDB

oom 内存溢出&#xff0c;内存泄漏&#xff0c;相当于TiDB不能用了 TiDB Server OOM对业务的影响 TiDB Server上的业务SQL会失败业务响应时间升高前端体验变差 诊断方法 客户端应用 ERROR 2013(HY000): Lost connection to MySQL Server during query日志 dmesg -T | gr…

【ArcGIS Pro二次开发】(54):三调名称转用地用海名称

三调地类和用地用海地类之间有点相似但并不一致。 在做规划时&#xff0c;拿到的三调&#xff0c;都需要将三调地类转换为用地用海地类&#xff0c;然后才能做后续的工作。 一般情况下&#xff0c;三调转用地用海存在【一对一&#xff0c;多对一和一对多】3种情况。 前2种情况…

Vben Admin学习笔记

Modal 弹窗 modal弹窗一般作为单文件组件被引用&#xff0c;下面是两段示例代码&#xff1a; 弹窗文件 Modal.vue // Modal.vue <template><BasicModal v-bind"$attrs" title"Modal Title" :helpMessage"[提示1, 提示2]">Modal I…

【动态规划part07】| 70.爬楼梯(进阶)、322.零钱兑换、完全平方数

目录 &#x1f388;LeetCode70. 爬楼梯 &#xff08;进阶&#xff09; &#x1f388;LeetCode322. 零钱兑换 &#x1f388;LeetCode279.完全平方数 &#x1f388;LeetCode70. 爬楼梯 &#xff08;进阶&#xff09; 链接&#xff1a;70.爬楼梯进阶 假设你正在爬楼梯。需要 …

官网HID描述符工具

USB规范官网提供了一个HID报告描述符生成工具&#xff0c;HID Descriptor Tool | USB-IF 使用我们此工具&#xff0c;我们可以&#xff1a; 创建、编辑和验证HID报告描述符。输出多种输出&#xff08;.txt、.inc、.h等&#xff09;查看一些标准的设备报告描述符示例。 该工具…

【NVMe2.0d 17 - 1】Reservation 介绍

文章目录 关键词概述Reservation 类型Reservation NotificationsSet Features Reservation Notification Mask (Feature Identifier 82h)Set Features Reservation Persistence (Feature Identifier 83h) 关键词 Reservation: Reservation Host:主机 Namespace:命名空间 NVM S…

C++ 核心编程

一、 内存分区模型 C程序在执行时&#xff0c;将内存大方向划分为4个区域 代码区&#xff1a;存放函数体的二进制代码&#xff0c;由操作系统进行管理 全局区&#xff1a;存放全局变量和静态变量以及常量 栈区&#xff1a;由编译器自动分配释放&#xff0c;存放函数的参数值、…

小程序如何将商品添加到分类

​将商品添加到分类是非常重要的功能&#xff0c;可以让商家更方便地管理分类和商品。下面将具体介绍如何将产品添加到分类中。 步骤一&#xff1a;选中商品 在个人中心点击管理入口&#xff0c;然后找到“商品管理”菜单并点击。找到需要添加的商品&#xff0c;然后选中它。…

初识C++——关键字,输入输出,函数名修饰,引用

文章目录 C的常用关键字C的输入输出C支持重载的原理------名字修饰windows下的名字修饰规则 引用引用的概念引用的特点使用场景做参数 做返回值常引用 C的常用关键字 C的常用关键字一共有63个&#xff0c;其中包括有C语言的关键字&#xff0c;这些关键字我们在后面的文章中都会…

如何高效实现文件传输:小文件采用零拷贝、大文件采用异步io+直接io

一般会如何实现文件传输&#xff1f; 服务器提供文件传输功能&#xff0c;需要将磁盘上的文件读取出来&#xff0c;通过网络协议发送到客户端。如果需要你自己编码实现这个文件传输功能&#xff0c;你会怎么实现呢&#xff1f; 通常&#xff0c;你会选择最直接的方法&#xf…

嵌入式学习_Day 003

程序功能介绍 c #include <stdio.h> int main() {char c,ll;printf("please enter a capital letter:");cgetchar();getchar();if (c>A&& c<Z) {llc32;printf("Lowercase letter output:%c\n",ll);printf("ASCII value:%d\n"…

阿含经人物传记知识图谱与问答系统设计20230725(进行中)

基本思路—— 1 数据提取 以《房山石经》阿含经为核心&#xff0c;提取经文索引、内容、关键词等数据&#xff0c;构成excel数据&#xff1b; 2 数据清洗 从数据库中重新建构角色画像数据&#xff0c;形成佛、辟支佛、尊者、比丘、比丘尼……等各类人物数据 3 数据映射&…

缠论线段的划分

第一种情况&#xff1a; 第二种情况&#xff1a; 第二种情况中的特例&#xff1a; 第二种情况的特例&#xff1a; 顶分型成立&#xff1a; 向上线段延续&#xff1a; 顶分型后面底分型&#xff0c;形成三段 插入一个分型的反面例子&#xff1a; dd