【Linux】解锁系统编程奥秘,高效文件IO的实战技巧

文件

  • 1. 知识铺垫
  • 2. C文件I/O
    • 2.1. C文件接口
    • 2.2 fopen()与重定向
    • 2.3. 当前路径
    • 2.4. stdin、stdout、stderr
  • 3. 系统文件I/O
    • 3.1. 前言
    • 3.2. open
      • 3.2.1. flags</h3>
      • 3.2.2. mode</h3>
      • 3.2.3. 返回值fd
    • 3.3. write</h2>
    • 3.4. read
    • 3.5. close</h2>
    • 3.6. lseek</h2>

1. 知识铺垫

  1. 文件=内容+属性。

文件属性、文件内容都是二进制数据,都需要占据磁盘的存储空间。

对文件的所有操作,本质上是要么对文件的内容做操作,要么对文件的属性做操作。

  1. 打开或修改文件,都是通过执行代码(如:文本编辑器)的方式来完成的。

文件打开、编辑、保存的流程:软件启动 -> 文件加载 -> 读取文件内容 -> 用户交互 -> 文件修改 -> 保存修改。

  1. 需要先打开文件,才能访问它 —> 将文件加载到内存中。

代码本身不能直接修改磁盘上的数据,CPU执行代码来修改这个文件时,实际上是在内存中进行的,因为CPU只能访问内存,所以磁盘的数据需要通过OS提供的文件系统调用接口和磁盘IO操作,来加载到内存中,然后CPU才能对这些数据进行处理。

  1. 谁在打开文件?进程。

打开文件之前,需要把访问这个文件的程序,编译形成的可执行程序,通过某种方式启动变成进程,等待cpu调度,执行完fopen后,文件才会打开。

  1. 一个进程可以打开多个文件吗?可以。

  2. 进程与文件的关系:结构体struct task_struct和结构体struct file之间的关系。

在一段时间内,系统存在多个进程,也可能同时存在多个被打开的文件,OS需要管理多个被打开的文件(先描述,再组织),所以内核中一定有描述被打开文件的结构体,并用其定义对象。

  1. 系统中是不是所有的文件都被打开了?不是,未打开的文件存放在磁盘中,被称为磁盘文件;打开的文件,存放在内存中,被称为内存文件。

2. C文件I/O

2.1. C文件接口

fopen、fclose

fread、fwrite; fgetc、fputc;fgets、fputs; fscanf、fprintf

fseek、ftell、rewind

feof、ferror

有关C文件接口,请看C语言博客中的文件内容,都有详细的介绍。

2.2 fopen()与重定向

  1. fopen以"w"方式打开:如果文件不存在,先会创建一个文件 / 如果文件存在,先会清空文件内容,然后再从头进行写入操作。
  • 相当于输出重定向(>)。
//文件以写的方式打开,如果文件不存在,新建文件 / 如果文件存在,先会清空文件内容,然后再从头进行写入操作
FILE *fp = fopen("example.txt", "w"); 
if (fp == NULL) {  //打开失败perror("Failed to open file"); return 1;
}fprintf(fp, "New content\n"); //向文件中进行写入
fclose(fp)  //关闭文件


2. fopen以"a"方式打开:本质也是写入,如果文件不存在,先会创建一个文件,然后进行写入 / 如果文件存在,会在文件原有内容的末尾处追加写入。

  • 相当于追加重定向(>>)。
//文件以追加的方式打开,如果文件不存在,先会创建一个文件,然后进行写入 / 如果文件存在,会在文件原有内容的末尾处追加写入
FILE *fp = fopen("example.txt", "a");
if (fp == NULL) {perror("Failed to open file");return 1;
}fprintf(fp, "Additional content\n");
fclose(fp);


3. fopen以"r"方式打开:读取文件的内容,如果文件不存在,则读取失败,返回NULL 。

  • 相当于输入重定向(<)。
//以读的方式打开文件,读取文件的内容,如果文件不存在,则读取失败,返回NULL 
FILE *fp = fopen("example.txt", "r");
if (fp == NULL) {perror("Failed to open file");return 1;
}char buffer[1024];
if(fgets(buffer, sizeof(buffer), fp) != NULL) //文件存在printf("%s", buffer);

2.3. 当前路径

  1. 当一个进程在启动时,它的当前工作目录(当前路径),通常是启动该进程时所在的路径。这个路径通常由父进程(Shell)决定,它会被保存到/proc/pid/cwd中。

fopen(“data.txt”,“w”),如果data.txt文件不存在,就会在当前路径下创建此文件。

int chdir(const char* path);

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>int main()
{ printf("self id:%d\n", getpid());printf("更改前:当前工作目录\n");sleep(25);chdir("/root/tmp");printf("更改后:当前工作目录\n");sleep(25);                                                     FILE* fp = fopen("110.txt","w"); //此处表示,如果不存在110.txt文件,就会在当前路径(cwd)下,创建此文件if(fp == NULL) return 1;fclose(fp);printf("文件创建成功\n");return 0;
}

2.4. stdin、stdout、stderr

一、标准输入流stdin

  1. 定义:标准输入是程序可以从中读取输入数据的位置,它默认指向键盘,但也可以被重定向为文件或者其他输入设备。

  2. 作用:允许用户通过键盘或者其他输入设备向用户提供数据,也可以从文件中读取数据。

  3. 文件描述符:在linux系统中,stdin文件描述符为0。

二、标准输出流stdout

  1. 定义:标准输出是程序用于发送其输出数据的位置,它默认指向终端屏幕,但也可以被重定向为文件或者其他输出设备。

  2. 作用:stdout用于显示程序的正常输出,包括结果、状态信息、其他非错误信息。

  3. 文件描述符:在linux系统中,stdout文件描述符为1。

  4. 缓冲:stdout通常是行缓冲的,意味着输出会先存储在缓冲区中,直到遇到换行符或者缓冲区满才会刷新到目的地。

三、标准错误输出流stderr

  1. 定义:标准错误是程序用于发送错误、异常信息的位置,它默认指向终端屏幕,但也可以被重定向为文件或者其他输出设备。

  2. 作用:用于输出错误信息,以便用户能够识别并解决问题。

  3. 文件描述符:在linux系统中,stderr文件描述符为2。

  4. 缓冲:stderr是非缓冲的,意味着错误信息会被立即发送到目的地,以便用户能够尽快的看到它。

💡注意:程序在启动时,默认会打开stdin、stdout、stderr流。即:可以直接使用它们,无需手动打开。

如:printf是向标准输出流stdout发送格式化数据,因为stdout在启动时已经被打开了,并关联到了输出设备(显示器),所以printf可以直接使用它们,而无需进行额外的打开操作。

问:为什么程序在启动时,默认会打开stdin、stdout、stderr流?

  • 原因:大部分的程序员,无论你用什么语言进行编程,需求就是让你的计算机去帮你加工和处理你的数据,就需要处理这三个问题(用户的数据从哪里来,计算完毕后怎么让用户看到对应的计算结果,计算过程中出错了怎么办),所以我们就需要stdin,给用户提供一个输入方式把数据输入进来,需要stdout,向一个特定的显示设备进行打印,方便给用户把计算结果显示出来,需要stderr,帮助用户把错误信息打印到特定设备中。大部分程序默认情况都要项你的程序输入数据,由你自己的程序计算完毕后,把结果进行返回,如果语言不提供,就需要程序员自己打开,太麻烦,所以程序默认给你打开这三个流(不用声明和定义,程序在启动时,就已经帮你初始化列表,直接使用就可以了)。

3. 系统文件I/O

3.1. 前言

一、访问文件不仅有C语言上的文件接口,OS必须提供对应的访问文件的系统调用接口。即:C标准库中的文件IO接口,底层一定封装了系统调用接口。

问:为什么C语言的文件接口,底层要封装对应的系统调用接口?

  1. 简化了操作,增强了安全性和稳定性。

文件进行读写操作,需要访问硬件,而OS作为软硬件资源的管理者,所以用户不能越过OS来直接访问硬件,OS会提供一组访问文件的系统调用接口 。

  1. 保证了语言的跨平台性、可移植性。

不同的操作系统有不同的系统调用接口和文件的操作机制。如果直接使用系统调用接口进行文件操作,那么编写的代码很难在不同OS之间移植。C语言标准库通过封装系统调用,为开发者提供了一套统一的文件操作接口,这样开发者就能够使用相同的代码,在不同OS上进行文件操作,提高了代码的跨平台性。

💡Tisp:如果让语言直接使用原生的系统接口,就注定了这个语言不具备跨平台性、可移植性。

二、在语言上,C、C++在访问文件时的接口和方式是不同的,在OS看来,底层原理是一样的,都是对底层系统调用接口的封装。

在C++中,主要是通过istream库中的fstream(ifstream、ofstream)类来实现,成员函数封装了对这些资源的操作,包括调用系统调用接口来实现底层的读写操作。

所有语言的文件操作不一样,但底层原理都是一样的,不随着意志而转移。上层就只要熟悉用法。

3.2. open

int open(const char* pathname,int flags);

  1. 功能:打开或创建一个文件。

  2. 参数pathname:要打开或者创建文件的路径名。

如果pathname为绝对路径时,当需要创建一个文件,会在pathname路径下创建它;

如果pathname为文件名时,当需要创建一个文件,会在当前路径(进程启动时所在的路径)下创建它。

  1. 返回值:打开成功,返回非负整数,即:文件描述符(用于后续文件操作);如果失败,返回-1,并设置errno以指示错误的原因。

fopen:"r"-> open:O_RDONLY
fopen:"w"-> open:O_WRONLY|O_CREAT|O_TRUNC
fopen:"a"-> open:O_WRONLY|O_CREAT|O_APPEND
  • 底层调用Open,传递不同的参数,在上层表现为fopen以r、w、a方式打开文件。即:不同的fopen风格,代表着open传递了不同的选项。

3.2.1. flags

  1. 参数flag:标记位,用于指定文件的打开模式(只读、只写、追加等)和其他选项(创建文件、截断文件等)。
//宏
#define O_RDONLY    0x00000000  // 只读模式  16进制
#define O_WRONLY    0x00000001  // 只写模式
#define O_RDWR      0x00000002  // 读写模式
//以上三个常量,必须且只能指定一个
#define O_CREAT     0x00000100  // 如果文件不存在,则创建文件
#define O_TRUNC     0x00000200  // 如果文件存在,则截断为零长度
#define O_APPEND    0x00000400  // 每次写入时追加到文件末尾
#define O_EXCL      0x00000800  // 如果文件已存在,则打开失败
#define O_NONBLOCK  0x00001000  // 非阻塞模式 
  1. flag参数是一个整数,每个比特位代表一个标记位。通过位操作(|、&),可以一次性向函数传递多个标记位。

在编程中,涉及需要向函数传递多个布尔选项(标记位)时,使用单个整数(int,32位),并通过位操作来设置和检查这些选项,这种方法被称为"位图",是一种非常高效和节省资源的方法。

  1. 使用宏定义,来表示各种标记位,每个宏定义只有一位为1(每个宏中为1的位是错开的),其余位全为0。在这个整数中为1的位,用来表示某个特定的选项是否被设置。多个宏通过位操作(|按位或)组合,一次性地向函数传递多个标记位。即:通过位图的方式,传递多个标记位。
#include<stdio.h> #define ONE 1
#define TWO (1 << 1)
#define THREE (1 << 2)
#define FOUR (1 << 3)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");
}int main(){print(ONE);printf("-----------\n");print(ONE|TWO);printf("-----------\n");print(ONE|TWO|THREE);  //相当于是将两个宏中为1的位,进行了合并printf("-----------\n");print(ONE|TWO|THREE|FOUR);                                                      printf("-----------\n");return 0;}

3.2.2. mode

  1. 参数mode:可选参数,用于创建文件时设置文件权限。
#include<stdio.h>
#include<sys/types.h>
#include<fcntl.h>int main()
{//以"w"方式打开文件,文件存在,就在当前路径下新建文件int fd = open("data.txt", O_WRONLY|O_CREAT|O_TRUNC);if(fd == -1)  //打开失败{perror("open");return 1;}return 0;                                              
}


现象:新建文件的权限乱码了。 -> 原因:新建文件,未设置文件权限。

#include<stdio.h>
#include<sys/types.h>
#include<fcntl.h>int main()
{//以"w"方式打开文件,文件存在,就在当前路径下新建文件int fd = open("data.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666);//int fd = open("data.txt", O_WRONLY|O_CREAT|O_TRUNC);if(fd == -1)  //打开失败{perror("open");return 1;}return 0;                                              
}

现象:文件权限并不是666。


现象:文件权限不为666。

原因:默认(最终)权限计算公式 = 起始权限 & (~umask值) , 本质是从起始权限中去掉在umask权限中出现的权限,如果在起始权限中某权限位不存在,但umask中该权限位存在,该权限位的结果为0,"去掉"不是删除。

mode_t umask(mode_t mask);

  • 功能:设置文件的权限掩码。

umask函数只会影响调用它的进程所创建的权限掩码,而不会对父进程或其他进程的权限掩码产生影响。

#include <sys/stat.h>
#include<stdio.h>
#include<sys/types.h>
#include<fcntl.h>int main()
{umask(0);  //只改变此进程所创建的权限掩码//以"w"方式打开文件,文件存在,就在当前路径下新建文件int fd = open("data.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666);//int fd = open("data.txt", O_WRONLY|O_CREAT|O_TRUNC);if(fd == -1)  //打开失败{perror("open");return 1;}return 0;                                              
}

3.2.3. 返回值fd

一、FILE*与fd的关系

在底层上,fd是文件描述符,用于标识一个打开的文件,用于后续的文件操作。在语言上,FILE*是C语言标准I/O库定义的类型,用于表示文件流,用于后续的文件操作 —> 所以FILE结构体对象必定封装了fd。

  • FILE类型是C语言IO库定义的一个结构体类型,用于表示一个流,这个流可以关联到一个文件、内存区域或其他输出/输入资源。FILE结构体内部封装了与流操作相关的各种信息(如:文件描述符fd、文件读写位置、缓冲区、文件状态等)。

  • 流:抽象的概念,它提供了统一的方式来处理数据的输入、输出,无论这个数据是来自于文件、标准输入输出(键盘、显示器)或其他形式的输入输出资源。流的本质是数据传输。

#include<stdio.h>
#include<sys/types.h>
#include<fcntl.h> int main()
{int fd1 = open("data1.txt", O_WRONLY|O_CREAT|O_TRUNC);int fd2 = open("data2.txt", O_WRONLY|O_CREAT|O_TRUNC);int fd3 = open("data3.txt", O_WRONLY|O_CREAT|O_TRUNC);printf("fd1:%d\nfd2:%d\nfd3:%d\n", fd1, fd2, fd3);printf("\n");                                          //FILEl类型是由C标准库封装的结构体printf("stdin:%d\n", stdin->_fileno);printf("stdout:%d\n", stdout->_fileno);printf("stderr:%d\n", stderr->_fileno);return 0;
}


二、C语言文件接口,不仅在接口上进行了封装,在类型上也进行了封装。

  1. 接口层面的封装

定义:将文件操作的具体实现隐藏起来,只向用户暴露了一组预定义的函数,用户就可以通过这组函数间接与文件系统进行交互。这种方式使得用户不需要了解文件系统背后复杂的机制。如:磁盘读写。

如:C语言标准库中的fopen、fclose、fread、fwrite等高级函数,底层封装了对应的系统调用接口open、close、read、write。用户通过这些函数可以打开文件、关闭文件、读取文件内容、写入文件内容,而不需要关心这些操作是如何在底层实现的。

  1. 类型层面的封装

定义:为文件操作定义了一个或多个特定的数据类型(如:FILE类型),用于表示文件状态和上下文。

如:FILE结构体封装了文件描述符、文件读写位置、缓冲区、文件状态等其他相关信息。

3.3. write

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

  1. 功能:向打开的文件中写入数据。

  2. 参数:fd,表示写入数据的文件或设备; buf,指向要写入数据的缓冲区的指针; count,要写入的字节数。

如果buf为const char*类型,strlen(buff),不需要在后面+1,即:不需要把字符串结束标志\0写入进去。因为c语言字符串以\0结尾,\0不是字符串内容,而是作为字符串结束标记,与文件无关,若把\0写入,则会造成乱码。

  1. 返回值:如果成功,返回实际写入的字节数。如果出错,则返回-1,并设置errno以指示错误。

3.4. read

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

  1. 功能:从打开的文件中读取数据。

  2. 参数:fd,表示要读取数据的文件或设备; buf,指向读取数据的缓冲区的指针; count,要读取的最大字节数。

  3. 返回值:如果成功,返回实际读取的字节数。如果出错,则返回-1,并设置errno以指示错误。如果到达文件末尾(EOF),则返回0。

3.5. close

int close(int fd);

  1. 功能:关闭一个打开的文件描述符。

  2. 返回值:如果成功,返回0。如果失败,返回-1,并设置errno以指示错误。

3.6. lseek

off_t lseek(int fd, off_t offset, int whence);

  1. 功能:移动文件指针的位置。

  2. 参数offset:是从whence指定位置开始的偏移量,以字节为单位(在左边,则为负值、在右边,则为正值)。

参数whence:指定偏移量的参考点。

  1. 返回值:如果成功,返回新的文件偏移量(相对于文件开头的字节数)。如果出错,则返回-1,并设置errno以指示错误。

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

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

相关文章

面试经典150题——删除有序数组中的重复项

目录 题目链接&#xff1a;26. 删除有序数组中的重复项 - 力扣&#xff08;LeetCode&#xff09; 题目描述 判题标准: 示例 提示&#xff1a; 解法一&#xff1a;双指针 Java写法&#xff1a; 运行时间 C写法&#xff1a; 运行时间 论屎山代码是如何出现的 时间复杂…

感知笔记2:ROS 视觉 - 沿线行走

如何在 ROS 中使用 OpenCV如何跟踪线路如何根据颜色查找不同元素跟踪多条路径并做出决定为线路跟踪创建基本的 PID 在本章中&#xff0c;您将学习如何使用 ROS 中最基本、最强大的感知工具&#xff1a;OpenCV。 OpenCV 是最广泛、最完整的图像识别库。有了​​它&#xff0c;…

Docker实操:安装MySQL5.7详解(保姆级教程)

介绍 Docker 中文网址: https://www.dockerdocs.cn Docker Hub官方网址&#xff1a;https://hub.docker.com Docker Hub中MySQL介绍&#xff1a;https://hub.docker.com/_/mysql ​ 切换到“Tags”页面&#xff0c;复制指定的MySQL版本拉取命令&#xff0c;例如 &#xff1a…

uv-ui组件的使用——自定义输入框的样式

一、官网的使用 二、自定义修改样式 我是在小程序中使用此组件 想要自定义修改样式的话&#xff0c;需要placeholderClass加上 placeholderStyle配合使用 tip1&#xff1a;单独使用placeholderClass&#xff0c;他只会第一次渲染时生效&#xff0c;输入文字再清除后就不生效…

十六,Spring Boot 整合 Druid 以及使用 Druid 监控功能

十六&#xff0c;Spring Boot 整合 Druid 以及使用 Druid 监控功能 文章目录 十六&#xff0c;Spring Boot 整合 Druid 以及使用 Druid 监控功能1. Druid 的基本介绍2. 准备工作&#xff1a;3. Druid 监控功能3.1 Druid 监控功能 —— Web 关联监控3.2 Druid 监控功能 —— SQL…

(蓝桥杯)STM32G431RBT6(TIM4-PWM)

一、基础配置 这个auto-reload preload是自动重装载值&#xff0c;因为我们想让他每改变一个占空比&#xff0c;至少出现一次周期 Counter Period(Autoreload Regisiter)这个设值为10000&#xff0c;那么就相当于它的周期是10000 脉冲宽度可以设置为占周期的一半&#xff0c;那…

Python酷库之旅-第三方库Pandas(123)

目录 一、用法精讲 546、pandas.DataFrame.ffill方法 546-1、语法 546-2、参数 546-3、功能 546-4、返回值 546-5、说明 546-6、用法 546-6-1、数据准备 546-6-2、代码示例 546-6-3、结果输出 547、pandas.DataFrame.fillna方法 547-1、语法 547-2、参数 547-3、…

opencv图像透视处理

引言 在图像处理与计算机视觉领域&#xff0c;透视变换&#xff08;Perspective Transformation&#xff09;是一种重要的图像校正技术&#xff0c;它允许我们根据图像中已知的四个点&#xff08;通常是矩形的四个角&#xff09;和目标位置的四个点&#xff0c;将图像从一个视…

Ubuntu 与Uboot网络共享资源

1、NFS 1.1 Ubuntu 下 NFS 服务开启 sudo apt-get install nfs-kernel-server rpcbind 等待安装完成&#xff0c;安装完成以后在用户根目录下创建一个名为“Linux”的文件夹&#xff0c;以后所有 的东西都放到这个“Linux”文件夹里面&#xff0c;在“Linux”文件夹里面新建…

[Simpfun游戏云1]搭建MC Java+基岩互通生存游戏服务器

众所周知&#xff0c;MC有多个客户端&#xff0c;像常见的比如Java Edition和基岩等&#xff0c;这就导致&#xff0c;比如我知道一个超级好玩的JE服务器&#xff0c;但我又想使用基岩版来玩&#xff0c;肯定是不行的&#xff0c;因为通讯协议不一样。 这就有一些人才发明了多…

搜索引擎onesearch3实现解释和升级到Elasticsearch v8系列(四)-搜索

搜索 搜索内容比较多&#xff0c;onesearch分成两部分&#xff0c;第一部分&#xff0c;Query构建&#xff0c;其中包括搜索词设置&#xff0c;设置返回字段&#xff0c;filter&#xff0c;高亮&#xff1b;第二部分分页和排序。第一部分是映射引擎负责&#xff0c;映射通用表…

常见中间件漏洞靶场(tomcat)

1.CVE-2017-12615 开启环境 查看端口 查看IP 在哥斯拉里生成一个木马 访问页面修改文件后缀和文件内容 放包拿去连接 2.后台弱⼝令部署war包 打开环境 将前边的1.jsp压缩成1.zip然后改名为1.war 访问页面进行上传 在拿去连接 3.CVE-2020-1938 打开环境 访问一下 来到kali …

错题集锦之C语言

直接寻址和立即寻址 算法的又穷性是指算法程序的运行时间是有限的 未经赋值的全局变量值不确定 集成测试是为了发现概要设计的错误 自然连接要求两个关系中进行比较的是相同的属性&#xff0c;并且进行等值连接&#xff0c;在结果中还要把重复的属性列去掉 赋值运算符 赋值…

【计算机网络篇】电路交换,报文交换,分组交换

本文主要介绍计算机网络中的电路交换&#xff0c;报文交换&#xff0c;分组交换&#xff0c;文中的内容是我认为的重点内容&#xff0c;并非所有。参考的教材是谢希仁老师编著的《计算机网络》第8版。跟学视频课为河南科技大学郑瑞娟老师所讲计网。 目录 &#x1f3af;一.划分…

无线安全(WiFi)

免责声明:本文仅做分享!!! 目录 WEP简介 WPA简介 安全类型 密钥交换 PMK PTK 4次握手 WPA攻击原理 网卡选购 攻击姿态 1-暴力破解 脚本工具 字典 2-Airgeddon 破解 3-KRACK漏洞 4-Rough AP 攻击 5-wifi钓鱼 6-wifite 其他 WEP简介 WEP是WiredEquivalentPri…

浅谈vue2.0与vue3.0的区别(整理十六点)

目录 1. 实现数据响应式的原理不同 2. 生命周期不同 3. vue 2.0 采用了 option 选项式 API&#xff0c;vue 3.0 采用了 composition 组合式 API 4. 新特性编译宏 5. 父子组件间双向数据绑定 v-model 不同 6. v-for 和 v-if 优先级不同 7. 使用的 diff 算法不同 8. 兄弟组…

2024年及未来:构筑防御通胀的堡垒,保护您的投资

随着全球经济的波动和不确定性&#xff0c;通货膨胀已成为投资者不得不面对的现实问题。通胀会侵蚀货币的购买力&#xff0c;从而影响投资的实际回报。因此&#xff0c;制定有效的策略来保护投资免受通胀影响&#xff0c;对于确保资产的长期增值至关重要。在2024年及未来&#…

nginx架构篇(三)

文章目录 一、Nginx实现服务器端集群搭建1.1 Nginx与Tomcat部署1. 环境准备(Tomcat)2. 环境准备(Nginx) 1.2. Nginx实现动静分离1.2.1. 需求分析1.2.2. 动静实现步骤 1.3. Nginx实现Tomcat集群搭建1.4. Nginx高可用解决方案1.4.1. Keepalived1.4.2. VRRP介绍1.4.3. 环境搭建环境…

口碑最好的头戴式耳机是哪些?高品质头戴式耳机对比测评揭晓

头戴式耳机以其出色的音质表现和舒适的佩戴体验&#xff0c;成为了音乐爱好者和日常通勤用户的热门选择。而在众多品牌和型号中&#xff0c;口碑最好的头戴式耳机是哪些&#xff1f;面对市场上丰富的选择&#xff0c;找到一款音质优良、佩戴舒适且性价比高的耳机并不容易。今天…

美畅物联丨技术前沿探索:H.265编码与畅联云平台JS播放器的融合应用

一、H.265 编码&#xff1a;视频压缩技术的重大变革 H.265&#xff0c;即被熟知为高效视频编码&#xff08;HEVC&#xff0c;High Efficiency Video Coding&#xff09;&#xff0c;由国际电信联盟电信标准化部门视频编码专家组&#xff08;ITU-T VCEG&#xff09;与国际标准化…