【Linux第七课--基础IO】内存级文件、重定向、缓冲区、文件系统、动态库静态库

目录

  • 引入
  • 内存级文件
    • 重新使用C文件接口 -- 对比重定向
      • 写文件
      • 读文件
      • 文件流
    • 认识文件操作的系统接口
    • open
      • 参数 -- flag
        • flag的内容
        • 宏的传参方式
      • open
      • 关闭文件
      • 写文件
      • 读文件
      • 结论
    • 引入文件描述符fd、对文件的理解
      • 理解一切皆文件
      • 方法集
      • 文件fd的分配规则
  • 重定向
    • 代码的重定向
      • 输入重定向
      • 输出重定向
      • 追加重定向
    • 指令重定向
      • 输入重定向
      • 输出重定向
      • 追加重定向
    • 修改之前的shell,让它支持重定向
  • 缓冲区
    • 概念
    • 在哪里
  • 磁盘级文件(文件系统)
  • 磁盘
      • 磁盘的机械构成
      • 磁盘的物理存储
      • 磁盘的逻辑存储
        • 1、红色部分
        • 2、蓝色部分
        • 文件的增删查改和路径有关
    • 具体的文件系统
  • 软硬链接
    • 原理
    • 应用场景
  • 动静态库
    • 回顾
    • 动态库的制作和使用
    • 理解动态库加载
      • 系统角度理解
      • 编址
      • 理解动态库动态链接和加载问题

引入

a、文件 = 内容 + 属性
b、访问文件之前,都得先打开。修改文件,都是通过执行代码的方式完成修改,文件必须被加载到内存中
c、进程在打开文件
d、一个打开多少个文件?可以打开多个

一定时间段内,系统中有多个进程,那么就有更多同时被进程打开的文件,OS要不要管理多个被进程打开的文件?肯定的,先描述再组织

e、进程和文件的关系,struct task_struct和struct xxxx
f、没有被打开的文件在哪?磁盘

内存级文件

重新使用C文件接口 – 对比重定向

写文件

文件创建的路径和进程有着很大的关系
在这里插入图片描述

tu
像文件里面写入内容:fputs
在这里插入图片描述
在这里插入图片描述

#include<stdio.h>int main()
{FILE* fp = fopen("./log.txt", "w");if(fp == NULL){perror("fopen");return 1;}const char* str = "hello linux\n";fputs(str, fp);fclose(fp);return 0;
}

文件打开再关闭就被清空了?
以w方式打开文件,该文件会被清空在这里插入图片描述
echo “xxxxxx” > log.txt
以a的方式打开,不会清空文件
在这里插入图片描述
echo “xxxxxx” >> log.txt

fwrite写入数据
第一个参数:写入文件的其实内存;第二个参数:写入数据的大小,每个基本单位的大小;第三个参数:写入几个基本单元;
返回值:写入了多少个基本单位

fputs:是写入字符串的形式,它是认识字符串,以\0结尾
fwrite:是以二进制流写入,不认识字符串

在这里插入图片描述
如果没有此文件,当指定绝对路径就会在绝对路径下创建这个文件,否则就在该进程所在目录下创建

int main()
{FILE* fp = fopen("log.txt", "w");if(fp == NULL){perror("fopen");return 1;}char* str = "hello file\n";int cnt = 5;while(cnt){int num = fwrite(str, strlen(str), 1, fp);cnt--;}fclose(fp);return 0;
}

那改变进程的路径,创建的这个文件也会变
在这里插入图片描述

读文件

fgets:一行读出

文件流

程序默认打开的文件流

stdin标准输入键盘设备
stdout标准输出显示器设备
stderro标准错误显示器设备

向显示器继续打印的方法
printf、fprintf、fwrite、fputs

int main()
{FILE* fp = fopen("./log.txt", "w");if(fp == NULL){perror("fopen");return 1;}//标准写入//默认想显示器写入,写入流是stdoutprintf("hello printf\n");//与printf略有不同,写入到哪里不是默认的fprintf(stdout, "hello fprintf\n");fprintf(fp, "hello fprintf\n");//char* str = "hello fputs";fputs(str, fp);fputs(str, stdout);//char* str2 = "hello fwrite";fwrite(str2, strlen(str2), 1, fp);fwrite(str2, strlen(str2), 1, stdout);fclose(fp);

标准输入的方法
scanf 、 fread、fscanf

	FILE* fp2 = fopen("./log.txt", "r");if(fp2 == NULL){perror("fopen");return 1;}char str3[64];scanf("%s", str3);printf("%s\n", str3);fscanf(stdin, "%s", str3);printf("%s\n", str3);fread(str3, strlen(str3), 1, stdin);fclose(fp2);

结论:stdin、stdout、stderro可以直接被使用

认识文件操作的系统接口

访问文件不仅仅有C语言上的文件接口,OS必须提供对应的访问文件的系统调用

w:会清空文件
a:追加文件
r:读取文件

open

在这里插入图片描述

返回值:成功–文件描述符, 失败—1
参数:flags
返回值:int类型的数据

参数 – flag

flag的内容

在这里插入图片描述
在这里插入图片描述

O_RDONY只读打开
O_WRONLY只写打开
O_RDWR读写打开
O_CREAT如果文件没有就创建
O_TRUNC当对已有内容文件做写入时,会对文件内容清空
O_APPEND每次文件打开向文件结尾处写,追加
宏的传参方式

如果传五个参,要设置五个参数比较低级,可以设置标志位
设置一个参数,参数类型是int, 每个bit位代表一个flag

#include<stdio.h>
#include<string.h>
#include<unistd.h>#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");return;
}int main()
{Print(ONE);printf("----------------------\n");Print(THREE);printf("----------------------\n");Print(ONE|TWO|THREE);printf("----------------------\n");Print(THREE|FOUR|FIVE);return 0;
}

daim
对于open函数中的flag参数也是如上那么使用

open

先学习三个参数的
mode : 权限设置

普通文件:0666

在这里插入图片描述

#include<stdio.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);close(fd);return 0;
}

在这里插入图片描述
两个参数的open在没有文件的时候也能创建,但是创建文件的权限是乱的
因此需要三个参数的open的第三个参数mode去设置创建文件的权限

#include<stdio.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);close(fd);return 0;
}

在这里插入图片描述
但是上面创建的文件的属性和我们设置的0666还是不一样的,它是0644。那是因为操作系统有自己的掩码umask

不使用系统的umask,想使用自己的可以在代码中使用umask()函数进行设置
在这里插入图片描述

在这里插入图片描述

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>int main()
{umask(0);int fd = open("log.txt", O_WRONLY|O_CREAT, 0666);close(fd);return 0;
}

在这里插入图片描述

如果文件存在,使用两个参数的open,如果文件不存在,使用三个参数的open

关闭文件

利用返回值关闭文件

用那个整数文件描述符
在这里插入图片描述
在这里插入图片描述

返回值
为何默认从3开始?0、1、2已经被用了,stdin – 0、stdout–1、stderror – 2
数组下标?

写文件

write

strlen(str)不要+1 : \0不是字符串的内容,是C语言规定字符串以、0结尾。写入就是乱码

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>int main()
{//写文件int fd = open("log.txt", O_WRONLY|O_CREAT, 0666);if(fd == -1){perror("open");return 1;}char* str = "hello world";ssize_t i = write(fd, str, strlen(str));if(i < 0){perror("write");return 1;}close(fd);return 0;
}

在这里插入图片描述

系统调用写文件,不会清空文件,直接覆盖式的往里写
在这里插入图片描述
参数flag使用O_TRUNC,即可清空文件里的内容再往里面写
在这里插入图片描述

读文件

在这里插入图片描述
返回值:ssize_t有符号的整数

fd:要读取文件的描述符
buf:读出的内容存放的缓冲区
count:放入内容最大可以存放多少

=0文件结束
<0读取错误
>0读取成功,读到多少个字符
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>int main()
{int fd = open("log.txt", O_RDONLY);char str[1024];ssize_t s = read(fd, str, sizeof(str)-1);str[s] = '\0';printf("%s\n", str);close(fd);

结论

1、C语言的文件接口,本质是封装了系统调用。不仅在接口进行封装,在类型上进行封装
2、FILE是C标准库自己封装的一个结构体,这个结构体里一定包含open返回的那个fd(0.1.2.3…)
3、为何C语言要封装?为了保证自己的跨平台性和可移植性
4、文件描述符的本质:数组下标

引入文件描述符fd、对文件的理解

文件描述符的本质:数组下标

理解一切皆文件

方法集

对于文件的描述struct file 里面有一块是函数指针,函数指针指向具体的硬件的调用方法

文件fd的分配规则

现象1:
关掉0文件,再打开自己文件,看其文件描述符
tu
最小的没有被使用的数组下标,会分配给最新打开的文件
现象2:
关掉1,打印时并没有在屏幕里打印出来,竟然把信息写入到了文件里面
输出重定向:语言层不变,在操作系统层进行更改
在这里插入图片描述

重定向

代码的重定向

输入重定向

输入重定向,从键盘输入的重定向,stdin – 0

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>int main()
{close(0);int fd = open("log.txt", O_RDONLY);char buffer[1024];while(1){char* s =  fgets(buffer, sizeof(buffer), stdin);if(s == NULL) break;printf("file content:%s", buffer);}close(fd);return 0;
}

输出重定向

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>int main()
{char* str = "hello world";int fd = open("log.txt", O_WRONLY|O_CREAT|O_APPEND, 0666);dup2(fd, 1);fprintf(stdout, "file %s\n", str);close(fd);return 0;
}

追加重定向

不想利用文件描述符的分配规则,直接打开,打开之后再拷贝到1的位置,也完成了重定向
在这里插入图片描述
在这里插入图片描述
最终只剩old

dup2(fd, 1);
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>int main()
{char* str = "hello world";int fd = open("log.txt", O_WRONLY|O_CREAT|O_APPEND, 0666);dup2(fd, 1);fprintf(stdout, "file %s\n", str);close(fd);return 0;
}

在这里插入图片描述

指令重定向

输入重定向

没有对应的文件会创建
在这里插入图片描述
什么也不做的时候会被清空
在这里插入图片描述

输出重定向

在这里插入图片描述

追加重定向

在这里插入图片描述

修改之前的shell,让它支持重定向

缓冲区

概念

缓冲区是一块内存空间
提高使用者效率
刷新:聚集数据,一次拷贝,提高整体效率
我们一直在说的缓冲区和内核中的缓冲区没有关系,语言层面的缓冲区,C语言自带缓冲区

调用系统调用是有成本的,时间&&空间
单次调用一次系统调用就可以完成工作是效率比较高的

在这里插入图片描述
语言层缓冲区刷新
(1)无刷新,无缓冲
(2)行刷新 ----- 显示器,XXXX\nYY
(3)全刷新 ----- 普通文件,缓冲区写满才刷新

例外
强制刷新
进程退出,要自动刷新
内核中的缓冲区
OS自主决定

在哪里

缓冲区在大写的FILE*内部,像stdin、stdout、stderror都是一个FILE里面都有一个缓冲区
如何证明这个缓冲区的存在呢?
在这里插入图片描述
在这里插入图片描述
子进程先退出,退出时对于缓冲区需要进行刷新,刷新就是修改,修改就要写时拷贝,因此打了两遍

缓冲区还要支持格式化输入输出的实现
键盘显示器的输入和显示都是字符级的,格式化输入输出,就是把字符转换成int、string...,或者int、string...转换成字符级的

磁盘级文件(文件系统)

如何让系统快速定位一个文件?
文件系统,通过路径快速定位文件

例如:菜鸟驿站取快递

磁盘

磁盘的机械构成

盘片、磁头(一面一个磁头)、马达、伺服系统(识别指令并控制盘片和磁头)

磁盘的物理存储

磁道/柱面:一圈
扇区:磁道中的某一部分成为扇区,磁盘IO的基本单位,不一定是系统的

当你想要修改某一个扇区中的一个bit位,必须把整个扇区加载到内存里,修改要修改的bit位,之后再将整个扇区的信息写入。一般512字节

磁头/盘面:一个磁头一个盘面,一个盘面一个编号

访问某一个扇区:
CHS定位法
1、通过磁头定位在哪个磁道/柱面 cylinder
2、使用哪一个磁头/盘面head
3、使用哪一个扇区sector

磁盘的逻辑存储

逻辑存储方便软件的编写
LBA地址logical block address
虽然把内容进行了抽象,但是一次管理这么多还是不容易,所有分成几块,分区
大的分区再分成很多很多组

一个文件一个inode(大小128字节)

删除文件:不会删除内容,只要把inode bitmap和block bitmap使用的置为0就好了
Linux磁盘文件的特性:内容+属性

内容和属性分开存储
内容大小不确定,可能很大,可能很小
属性固定大小的
文件名不属于文件属性

ll -i //显示inode

在这里插入图片描述
系统中,表示一个文件吧不是用文件名,而是inode
每个inode的大小:128字节

inode Bitmap:知道inode Table的使用情况
Data blocks:数据区
Block Bitmap:块位图
Group Descriptor Table:块组描述符表

系统里面创建一个文件的步骤
在某一个块创建一个文件,首先查Inode Bitmap找一个没有被使用的inode,将该文件的相关属性写到找的那个inode在inode table里面。当对此文件进行写入数据的时候,先查Block Bitmap看看数据区的哪一块可以使用,写入到数据区相应的块。之后在该文件的inode里面的有个int block[15]写到这里面,让文件知道自己用了哪个块

inode在整个分区内唯一
在这里插入图片描述

1、首先确定inode在哪个组里

1、红色部分

对于一个文件,int block只有15块吗,这么小?不是的,有直接索引、间接索引、三级索引
在这里插入图片描述

2、蓝色部分

在这里插入图片描述
GDT,Group Descriptor Table:块组描述符,对分组进行管理,描述块组属性信息
超级块(Super Block)存放整个分区情况,对分区做管理,一个文件系统对应一个super block。一个区里选n个group里面有super block,内容是一致的
在这里插入图片描述
每个分区可以写入相同或不同的文件系统 — super block

目录是不是文件?是。inode(inode编号)+ 目录的内容(文件名和inode的映射)
当目录没有w权限,在该目录里面就没法创建文件,没法删除文件
当目录没有r权限,就读不到文件名和inode的映射信息,也就读不到该目录下的文件信息

创建文件
(1)查询inode bitmap查找哪个inode没有用,在相应位置创建inode
(2)将inode编号和文件名的对应写在相应目录的内容里
删除一个文件
(1)从目录里面找到要删文件名对应的inode
(2)将inode bitmap和block bitmap该文件使用的位置设置为0
(3)删除该文件在相应目录内容里的inode和文件名的对应

那么访问目录的内容也是需要inode的,哪里来的

文件的增删查改和路径有关

根目录的inode,开机OS是知道的
查一个文件:在内核中,都要逆向的递归般得到/,从根目录进行路径解析

struct dentry{ }每打开一个路径都会缓存路径,缓存成一个dentry

一个被写入文件系统的分区,要被linux使用,必须要先把这个具有文件系统的分期进行==“挂载”==

挂起:一个文件系统所对应的分区,挂载在对于目录里面
每一个分区都会挂载在一个目录下在这里插入图片描述
访问一个文件,可以根据路径前缀,优先区分文件在哪一个分区下

具体的文件系统

软硬链接

原理

软连接
在这里插入图片描述

软链接本质:是一个文件,因为它有自己的inode
软件内容放的是目标文件的路径,类似快捷方式

硬链接
在这里插入图片描述

硬链接:本质不是一个独立的文件,因为它的inode编号和目标文件的一样。一定没有新建文件
是新的文件名,和目标文件inode号的映射关系,写入到指定的目录的数据库中

硬链接像重命名,引用计数
在这里插入图片描述
在这里插入图片描述

应用场景

删除一个文件

rm -f 文件名
unlink 文件名

1、软链接
当我们写了一个项目mytest要传给其他人,不想把原始代码传给他,只传bin、conf、log、myexe
在这里插入图片描述
对方要运行myexe就需要./bin/myxe这样很麻烦,因此可以用一个软连接
在这里插入图片描述
2、硬链接
当创建一个空文件的时候,它的硬链接数就是2,为什么?
在这里插入图片描述
因为他有一个.
在这里插入图片描述

OS不允许用户自己给目录简历硬链接,因为会形成环路问题
OS可以自己建立,eg. ..

动静态库

回顾

1、默认安装的是动态库,云服务器,静态库(c标准库)默认没有安装
2、默认编译程序,用的是动态链接的

动态库的制作和使用

为什么要有库?
提高开发效率
隐藏源代码

1、建立静态库

当没有源代码的时候,只有.o .h就可以使用里面的方法
假设我有一些写好的方法,user这个用户想要使用,但我不想给他我的源代码,就可以只给他.o .h文件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

但是当.o文件很多的时候很麻烦,而且难免会有遗漏的

ar -rc libmyc.a  打包文件 打包文件

在这里插入图片描述
库名:myc,去掉前缀、去掉后缀
在这里插入图片描述

-l:链接哪个库
-L:连接的库在什么地方,因为系统只默认知道lib64下的,所以这要指明

在这里插入图片描述
2、形成动态库并发布
转换成.o文件
fPIC :产生位置无关码

//形成.o文件
gcc -c -fPIC 文件名

动态库打包
shared:表示生产共享库格式

gcc -shared -o libxxx.so xxxx.o xxxx.o

库的名字以so结尾
在这里插入图片描述
但此时给使用者动态库,还是需要给动态库、.h等文件,我们可以把它们合并成一个

libmyc.so: mymath1.o mymath2.ogcc -shared -o $@ $^%.o:%.cgcc -c -fPIC $<
#mymath1.o:mymath1.c
#	gcc -c -fPIC $<
#mymath2.o:mymath2.c
#	gcc -c -fPIC $<.PHONY:clean
clean:rm -f *.o mylib libmyc.so.PHONY:output
output:mkdir -p mylib/includemkdir -p mylib/libcp -rf *.h mylib/includecp -rf *.so mylib/lib

其中$<代表依赖的对象从左到右一个一个执行

在这里插入图片描述
还可以吧mylib压缩一下
在这里插入图片描述
在这里插入图片描述

不想使用-L:把这个库拷贝到/lib64

//看可执行程序连接了那些库                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
ldd xxx.out

4、用户下载
在这里插入图片描述

下载使用很麻烦,把.h和库拷贝到默认路径下,就可以不用带了
在这里插入图片描述

所谓的把库(其他软件)安装到系统中,本质就是把文件拷贝到指定路径

在这里插入图片描述
在这里插入图片描述

5、卸载
不建议把自己写的不成熟的库写到默认路径里
在这里插入图片描述

注意
静态库只需要编译的时候使用,之后运行什么的就不需要了(只影响编译阶段)
动态库:(1)编译时搜索路径 ---- gcc(2)运行时的搜索路径 — 操作系统
对于动态库在编译的时候可以跑通,运行的时候又找不到库了
在这里插入图片描述

解决方法
1、把自己的库拷贝到默认路径下/lib64,既可以支持编译、又可以支持运行
2、将不在系统默认库搜索路径下的库连接,添加到LD_LIBERERY_PATH
在这里插入图片描述:系统运行程序时,动态库查找时的辅助,:为分隔符
export LD_LIBERERY_PATH=$LD_LIBRARY_PATH:具体路径
问题:重新登陆就没有了,但是在家目录里面的.bashrc里配置
3、对库文件在默认库路径下建立同名软连接
4、配置文件:把路径放到配置文件里就可以
/etc/ld.so.conf.d在该目录下创建配置文件
ldconfig使配置文件生效

理解动态库加载

1、同时形成动静态库,默认动态链接
2、非要静态链接必须使用选项-static
3、如果只提供静态库,那我们的可执行程序也没办法,只能对该库进行静态链接,但是程序不一定整体是静态链接
4、如果只提供动态库,默认只能动态链接,非得静态链接,会发生连接报错

系统角度理解

库函数的调用,依旧在进程的地址空间中进行的
动态库加载之后,会映射到进程的共享区

1、谁来决定,哪些库加载了,那些没加载?OS会自动决定
2、系统中可以同时有多个库吗?可以
3、操作系统对这些库先描述再组织

编址

可执行程序加载之前,就有地址
我们进程地址空间里面很多地址数据,是从可执行程序里面来的(因为不同的可执行程序,他的数据段和代码段是不一样的,进程初始化进程地址空间每块多大的时候就是根据可执行程序)
可执行程序编制方式:
绝对编址方式—平坦模式(从0开始编址)
相对地址—逻辑编制(偏移量)
==虚拟地址空间本身不仅OS要遵守,编译器编译程序的时候,也要遵守

理解动态库动态链接和加载问题

1、进程的地址空间既然是一个数据结构对象,谁来用什么数据初始化呢?
可执行程序本身在加载到内存之前,根据自身表头的数据部分初始化进程地址空间的数据段、代码段等的begin end

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

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

相关文章

创意设计的起点:十大网页设计模板网站

对于网页设计领域的专业人士和爱好者而言&#xff0c;从零开始构建一个网页可能会耗费大量的时间和劳力。幸运的是&#xff0c;我们可以通过使用现成的网页模板来提升工作效率并节省宝贵的时间。一个好的模板不仅能提高设计效率&#xff0c;还能激发出卓越的创意灵感。因此&…

鸿蒙Harmony-矩形绘制组件Rect使用详解

目录 一&#xff0c;定义 二&#xff0c;绘制自定义图形 三&#xff0c;作为其他控件背景使用 一&#xff0c;定义 Rect是鸿蒙提供的矩形绘制组件&#xff0c;利用该组件可以绘制矩形背景&#xff0c;矩形图案等 官方提供的参数和属性&#xff1a; 参数&#xff1a; 参数名…

netty之bootstrap源码分析

写在前面 本文看下bootstrap类。 1&#xff1a;正文 1.1&#xff1a;干啥的&#xff1f; 在进行netty编程的时候都是先创建一个bootstrap&#xff0c;然后设置很多的东西&#xff0c;如下代码&#xff08;服务端启动代码&#xff09;&#xff1a; ServerBootstrap b new …

c# WinForm弹出窗体时不获取焦点方法

WinForm开发的软件有时候需要在屏幕右下角弹窗进行一些提示&#xff0c;通常使用new MyForm().Show()即可实现此需求。 但是当MyForm显示出来时&#xff0c;会抢走原本窗体上的光标&#xff0c;导致原本在软件上比如打字或者其他操作被中断&#xff0c;非常不人性化&#xff0…

方差和标准差哪些事儿

1.方差 在概率论与数理统计中&#xff0c;方差用来度量随机变量和其数学期望&#xff08;即均值&#xff09;之间的偏离程度。方差是各个数据与平均数之差的平方和的平均数,即: s(1/n)[(x1-x_)^2 (x2-x_)^2 …(xn-x_)^2] 其中&#xff0c;x_表示样本的平均数&#xff0c;n表示…

Hudi Upsert原理

1. 前言 如果要深入了解Apache Hudi技术的应用或是性能调优&#xff0c;那么明白源码中的原理对我们会有很大的帮助。Upsert是Apache Hudi的核心功能之一&#xff0c;主要完成增量数据在HDFS/对象存储上的修改&#xff0c;并可以支持事务。而在Hive中修改数据需要重新分区或重…

了解SQLExpress数据库

SQLExpress&#xff08;Microsoft SQL Server Express&#xff09;是由微软公司开发的一款免费且轻量级的数据库管理系统。以下是关于SQLExpress的详细解释&#xff1a; 一、定义与特点 定义&#xff1a; SQLExpress是Microsoft SQL Server的一个缩减版或基础版&#xff0c;旨在…

空天地遥感数据识别与计算

在科技飞速发展的时代&#xff0c;遥感数据的精准分析已经成为推动各行业智能决策的关键工具。从无人机监测农田到卫星数据支持气候研究&#xff0c;空天地遥感数据正以前所未有的方式为科研和商业带来深刻变革。然而&#xff0c;对于许多专业人士而言&#xff0c;如何高效地处…

JavaEE-多线程初阶(2)

目录 1.创建线程的五种写法 1.1 继承Thread类 1.2 实现Runnable接口 1.3 使用匿名内部类 1.4 使用Runnable&#xff0c;匿名内部类 1.5 引入lambda表达式 2.Thread类及常见方法 2.1 认识Thread 2.2 Thread的常见构造方法 2.3 Thread的几个常见属性 关于后台线程 关…

【网络安全】揭示 Web 缓存污染与欺骗漏洞

未经许可,不得转载。 文章目录 前言污染与欺骗Web 缓存污染 DoS1、HTTP 头部超大 (HHO)2、HTTP 元字符 (HMC)3、HTTP 方法覆盖攻击 (HMO)4、未键入端口5、重定向 DoS6、未键入头部7、Host 头部大小写规范化8、路径规范化9、无效头部 CP-DoS10、HTTP 请求拆分Web 缓存污染与有害…

重工业数字化转型创新实践:某国家特大型钢铁企业如何快速落地基于实时数仓的数据分析平台

使用 TapData&#xff0c;化繁为简&#xff0c;摆脱手动搭建、维护数据管道的诸多烦扰&#xff0c;轻量替代 OGG, Kettle 等同步工具&#xff0c;以及基于 Kafka 的 ETL 解决方案&#xff0c;「CDC 流处理 数据集成」组合拳&#xff0c;加速仓内数据流转&#xff0c;帮助企业…

Golang | Leetcode Golang题解之第522题最长特殊序列II

题目&#xff1a; 题解&#xff1a; func isSubseq(s, t string) bool {ptS : 0for ptT : range t {if s[ptS] t[ptT] {if ptS; ptS len(s) {return true}}}return false }func findLUSlength(strs []string) int {ans : -1 next:for i, s : range strs {for j, t : range s…

(C#面向初学者的 .NET 的生成 AI) 第 1 部分-简介

第 1 部分简介就是由Luis Quintanilla讲述本系列教程要学习哪些部分&#xff0c;基本都是介绍&#xff0c;内容不是很多。但可以先了解一下.net 生成式AI需要学习接触哪些东西。 在这个关于机器学习和AI的初学者系列中&#xff0c;Luis Quintanilla向.net开发人员介绍了基础知识…

【密码学】全同态加密基于多项式环计算的图解

全同态加密方案提供了一种惊人的能力 —— 能够在不知道数据具体内容的情况下对数据进行计算。这使得你可以在保持潜在敏感源数据私密的同时&#xff0c;得出问题的答案。 这篇文章的整体结构包括多项式环相关的数学介绍&#xff0c;基于多项式环的加密和解密是如何工作的&…

Spring Boot中解决BeanDefinitionStoreException问题的实战分享

目录 前言1. 问题背景2. 问题分析2.1 异常分析2.2 常见的错误原因2.3 排查过程 3. 解决方案3.1 清理缓存和重建项目3.1.1 清理IDEA缓存3.1.2 使用Maven清理并重建项目 3.2 升级Maven版本3.2.1 下载最新Maven版本3.2.2 IDEA配置新的Maven版本3.2.3 清理缓存并重新构建 3.3 验证问…

Java避坑案例 - 线程池未复用引发的故障复盘及源码分析

文章目录 问题现象问题定位问题代码根因分析现象剖析newCachedThreadPool 源码SynchronousQueue特点构造方法主要方法应用场景Code Demo运行结果 问题修复 问题现象 时不时有报警提示线程数过多&#xff0c;超过2000 个&#xff0c;收到报警后查看监控发现&#xff0c;瞬时线程…

AHB Matrix 四星级 验证笔记(1.8-1.9)scoreboard的实现

文章目录 前言一、scoreboard接收数据的方式和比较行为的策略选择1.接受数据的方式1. 首先是数据从哪儿来&#xff1f; 2.比较数据的方式1.方案一2.方案二3. 方案的选择 二、scoreboard的实现1.代码 三、tip1.编辑断点2. return3.有关函数的返回值&#xff1a;函数内部隐式声明…

商业潜规则揭秘:从成交艺术到客户满意度的全方位策略

潜规则一&#xff1a;成交的艺术——七大核心原则 顾客追求的是超值感&#xff0c;而非单纯低价。 与顾客讨论的重点应是价值&#xff0c;而非价格。 客户没有绝对的对错&#xff0c;关键在于服务是否到位。 销售方式比销售产品本身更重要。 没有绝对最好的产品&#xff0c;只有…

在IDEA2024中生成SpringBoot模板

1、创建新项目 根据自己想要创建的工程类型选择&#xff0c;这里创建的时web工程 生成项目&#xff1a; 注意&#xff1a;SpringBoot只会扫描主程序所在的包及其下面的子包

物流行业信息化整体规划方案|117页PPT

文件是关于“物流行业信息化整体规划方案”的详细规划报告&#xff0c;涵盖了物流信息化咨询项目的规划报告&#xff0c;包括业务理解与需求分析、信息化现状分析、信息化蓝图规划以及实施路径与保障措施等多个方面。以下是对文档内容的总结&#xff1a; 1. 引言&#xff1a;信…