【Linux】简介磁盘|inode|动静态库

news2024/11/15 4:48:47

目录

  • 一.简介磁盘
    • 1.磁盘的物理结构:
    • 2.磁盘存储方式:
    • 3.磁盘的逻辑抽象:
  • 二.inode&&文件系统
    • 1.inode
      • 文件=属性(inode)+内容(data block)
      • 为什么删除一个文件相比于写一个文件要快得多?
    • 2.硬链接&&软链接
    • 3.特殊的隐藏目录`.`和`..`
    • 4.acm时间
  • 三.动态库和静态库
    • 1.生成静态库
      • 静态链接:
      • 静态链接的优缺点
    • 2.生成动态库
      • 如何运行动态库?
      • 动态链接:
      • 动态库的加载过程:

一.简介磁盘

在介绍Linux文件系统的时候先简单的介绍一下企业里比较常用的存储介质——磁盘

1.磁盘的物理结构:

在这里插入图片描述

盘片:
一个磁盘由多个盘片叠加而成。盘片的表面涂有磁性物质,这些磁性物质用来记录二进制数据。因为正反两面都可涂上磁性物质,故一个盘片可能会有两个盘面。
磁道、扇区:
每个盘片被划分为一圈一圈的磁道,将磁道划分为若干个小的区段,就是扇区。虽然很小,但实际是一个扇子的形状,故称为扇区(每个扇区的容量默认为512字节),每个磁道又划分为一个一个的扇区(上面用红线描出来的区域)。从图中可以看出,最内侧磁道上的扇区面积较小,而外侧磁道上的扇区面积较大,但是每个扇区一般来讲所存储的容量是相同的,因此内侧的扇区数据密度最大,外侧的扇区数据密度小。
柱面:
所有盘面中相对位置相同的磁道组成柱面,柱面数==磁道数,柱面就是磁道。
磁头:
通过磁性原理读取磁性介质上数据的部件。磁头和盘面没有接触,并且几个磁头来回摆动是共进退的。

2.磁盘存储方式:

磁盘寻址的时候,基本单位不是bit,更不是byte。而是扇区(默认情况下,扇区大小是512byte)。那么在盘面上如何定位一个或多个扇区呢?——CHS定位法
先定位在哪一个磁道(柱面Cylinder),然后再定位在哪一个磁头(Heads)也就是定位盘面,最后定位在哪一个扇区(Sector)。

3.磁盘的逻辑抽象:

一整个磁盘从上到下有很多扇区,不方便管理,我们把整个磁盘从逻辑上看做成一个sector_array[n]的数组这样的线性结构。把对磁盘的管理,转化为对这个数组的管理。那通过这个数组,怎么找到扇区呢?
在这里插入图片描述

假如盘面为4,每个盘面的磁道数为10,每个磁道的扇区数为100,每一面就有10*100=1000个扇区。
假如要找123号磁盘的位置,也就是n==123,那么就
先用123/1000=0 那么就在0号盘面,
再用123/100=1 那么就在1号磁道,
最后用123%100=23 也就是23号扇区。
通过类似这样的方式就可以知道盘面、磁道、扇区各是多少。而通过这个数组的下标就可以找到对应的地址,这个地址就叫做LBA地址。
推荐阅读

为什么OS要进行LBA逻辑抽象呢?直接用CHS不行吗?
1.便于管理。很显然用数组下标比三元组信息(CHS)要方便一些。
2. 不想让OS的代码和硬件强耦合。我们知道存储介质不一定只有磁盘,还有ssd、U盘等等,在OS看来都是LBA地址,对于不同的存储介质,只需要将LBA地址转换成对应的这些存储介质对应的存储地址即可,并不会影响OS。

二.inode&&文件系统

磁盘很大那怎么管理呢?磁盘被分为不同的分区,不同的分区又分为不同的分组。通过分治的思想一层一层的往上走,管好每一个分组,将类似的方法运用到每一个分组即可。

在这里插入图片描述

虽然对应的磁盘的访问的基本单位是扇区512byte,但是依旧很小!!OS内的文件系统定制的进行多个扇区的读取1KB或者2KB或者4KB为基本单位。你哪怕只想读取/修改1bit,必须将4KB加载到内存,进行读取或者修改,如果必要,再写回磁盘,和局部性原理有关系。

1.inode

为了能解释清楚inode我们先简单了解一下文件系统
在这里插入图片描述

拿Linux ext2文件系统为例,上图为磁盘文件系统图(内核内存映像肯定有所不同),磁盘是典型的块设备,硬盘分区被划分为一个个的block。一个block的大小是由格式化的时候确定的,并且不可以更改。例如mke2fs的-b选项可以设定block大小为1024、2048或4096字节。而上图中启动块(Boot Block)的大小是确定的,

  • Block Group:ext2文件系统会根据分区的大小划分为多个Block Group。而每个Block Group都由着相同的结构组成。
  • 超级块(Super Block):存放整个文件系统本身的结构信息。往往会在不同的组中各存一份,万一一个分组的Super Block被损坏了,把其他组的Super Block复制到过来就可以进行修复。记录的信息主要有:bolck 和 inode的总量,未使用的block和inode的数量,一个block和inode的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其他文件系统的相关信息。若Super Block的信息被破坏,可以说整个文件系统结构就被破坏了。
  • GDT,Group Descriptor Table:块组描述符,描述对应分组的属性信息。
  • 块位图(Block Bitmap):Block Bitmap中记录着Data Block中哪个数据块已经被占用,哪个数据块没有被占用,被占用了就用1表示,没有被占用就用0来表示。数据块对应的位图结构,位图中的比特位位置和当前data block对应的数据块位置是一一对应关系!
  • inode位图(inode Bitmap):每个bit表示一个inode是否空闲可用,被占用了就用1表示,没有被占用就用0来表示。位图中比特位的位置和当前文件对应的inode的位置是一一对应的!

文件=属性(inode)+内容(data block)

  • inode(inode Table):存放分组内部所有文件的属性。包括文件大小、所有者、最近修改时间等(但inode中不包含文件名,那哪里存放文件名呢?Linux下一切皆文件,目录也不例外,存放这个文件的目录的data blocks中,才存放着文件名和inode的映射关系
    而且inode为了区分彼此,每一个inode都有自己的一个ID号。
  • 数据块(Data blocks):保存的是分组内部所有文件的数据。

为什么删除一个文件相比于写一个文件要快得多?

  • 如果我们想创建一个文件。先确认你在哪个路径下,根据路径去找inode的bitmap,先帮你找一个没有被使用的inode,然后把inode属性填进去,然后如果你有内容的话在block bitmap里,帮你把数据给你写进去。比特位置好,数据写好。然后把inode的属性填完,inode的信息直接返回,返回之后,然后再向当前目录下对应数据块里面写inode编号和文件名对应的映射关系就可以了,这就叫做创建文件
  • 如果想删除文件,那么先由路径找到对应inode,然后由inode找到块位图和inode位图把对应的位置由1置0即可。
    所以这就是为什么删除一个文件相比于写一个文件要快得多的原因。
  • 所以说如果数据被误删了,我们最好什么都不做,不进行数据io,数据有被完整恢复的可能性。

2.硬链接&&软链接

真正找到磁盘上文件的并不是文件名,而是通过inode。 其实在linux中可以让多个文件名对应于同一个inode。
下图为软硬链接的操作:
在这里插入图片描述
解除链接用nulink def或者rm都可以。

  • abc和def被称为指向文件的硬链接,所谓硬链接就是在指定的路径下,新增文件名和inode编号的映射关系!内核记录了这个链接数,inode编号为926835的硬链接数为2。

让两个inode编号都指向同一个inode:
在这里插入图片描述

我们在删除文件时干了两件事情:

  • 1.在目录中将对应的记录删除。
  • 2.将硬连接数-1,如果硬链接数(count)为0(引用计数),此时文件才会真正的从磁盘被释放。
  • 硬链接是通过inode引用另外一个文件,软链接是通过路径引用另外一个文件。
  • 软链接相当于windows操作系统下的快捷方式,它内部保存的是被引用文件的文件路径。
  • 软硬链接区别:是否具有独立的inode。
    在这里插入图片描述

软硬链接有什么用?
软链接在动态库中有很大作用,后面会有详细介绍。

3.特殊的隐藏目录...

  • 一个普通文件创建之后默认的硬链接数是1;
  • 一个目录(假设目录名为empty)创建的默认硬链接数是2,因为除了自己,还有一个.表示它当前路径的硬链接。
    如果在这个目录empty里再创建一个目录dir,则此时empty硬链接数就变成3了,因为dir在中的..就代表empty这个目录,所以硬链接数变成3了。

⚠️ ...是操作系统自动创建的目录硬链接,但是Linux是不允许用户自己对目录进行硬链接的创建的。
因为如果给当前目录创建一个硬链接的话,那么在查找的时候会造成死循环,无法停下来。可能把目录树变为一环形图从而通过名字无法定位一个文件。

[root@VM-8-9-centos test]# ll -ai
total 12
 927203 drwxr-xr-x   3 root root 4096 Jan 18 19:38 .
 393219 dr-xr-x---. 16 root root 4096 Jan  4 18:49 ..
1049182 drwxr-xr-x   3 root root 4096 Jan 18 19:41 empty
 926835 -rw-r--r--   1 root root    0 Jan 18 19:38 test.txt

[root@VM-8-9-centos empty]# ll -ai
total 12
1049182 drwxr-xr-x 3 root root 4096 Jan 18 19:41 .
 927203 drwxr-xr-x 3 root root 4096 Jan 18 19:38 ..
1049184 drwxr-xr-x 2 root root 4096 Jan 18 19:41 dir
1049183 -rw-r--r-- 1 root root    0 Jan 18 19:39 test.c

[root@VM-8-9-centos dir]# ll -ai
total 8
1049184 drwxr-xr-x 2 root root 4096 Jan 18 19:41 .
1049182 drwxr-xr-x 3 root root 4096 Jan 18 19:41 ..

4.acm时间

[root@VM-8-9-centos empty]# stat test.c 
  File: ‘test.c’
  Size: 0         	Blocks: 0          IO Block: 4096   regular empty file
Device: fd01h/64769d	Inode: 1049183     Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2023-01-18 19:39:47.634929230 +0800
Modify: 2023-01-18 19:39:47.634929230 +0800
Change: 2023-01-18 19:39:47.634929230 +0800
 Birth: -
  • Access:文件最后访问时间。例如通过cat查看文件,这个时间可能不会访问一次就改变一次,我们对一个文件往往会频繁的访问,如果真的实时更新的话,那么效率会有所下降,所以会访问一定次数或者时间之后才会改变这个Access时间。
  • Modify:文件内容最近被修改的时间。但一般内容被修改了,文件的大小属性也就改变了,Change也就跟着被修改了。
  • Change: 文件的属性最近被修改的时间。

三.动态库和静态库

  • 静态库(libxxxxxx.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库

  • 动态库(libxxxxxx.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。

  • 库文件名称 如:libc.so -> c库,去掉前缀lib,去掉后缀.so,.a

库思想的引入:
如果我们不想直接给对方我们方法的源代码,但是还想让别人去用怎么办呢?下面拿比较简单的加法和减法举一个例子。
测试程序:

/add.h/
#pragma once
int add(int a, int b);
/add.c/
#include "add.h"
int add(int a, int b)
{
	return a + b;
}
/sub.h/
#pragma once
int sub(int a, int b);
/sub.c/
#include "sub.h"
int sub(int a, int b)
{
	return a - b;
}
///main.c
#include <stdio.h>
#include "add.h"
#include "sub.h"
int main(void)
{
	int a = 10;
	int b = 20;
	printf("add(%d, %d)=%d\n", a, b, add(a, b));
	a = 100;
	b = 20;
	printf("sub(%d,%d)=%d\n", a, b, sub(a, b));
}

把add.c和sub.c通过gcc -c得到add.o和sub.o这两个可重定位目标二进制文件。

[root@localhost linux]# gcc -c add.c -o add.o
[root@localhost linux]# gcc -c sub.c -o sub.o

gcc/g++的使用
接下来没有头文件,编译不通过

[hb@VM-8-9-centos ~]$ ll
total 16
-rw-rw-r-- 1 hb hb 1240 Jan 30 11:25 add.o
-rw-rw-r-- 1 hb hb  221 Jan 30 11:31 main.c
-rw-rw-r-- 1 hb hb 1240 Jan 30 11:25 sub.o
[hb@VM-8-9-centos ~]$ gcc main.c add.o sub.o 
main.c:2:17: fatal error: add.h: No such file or directory
 #include "add.h"
                 ^
compilation terminated.

再给头文件编译就通过了。

[hb@VM-8-9-centos ~]$ ll
total 36
-rw-rw-r-- 1 hb hb   56 Jan 30 12:07 add.h
-rw-rw-r-- 1 hb hb 1240 Jan 30 11:25 add.o
-rw-rw-r-- 1 hb hb  221 Jan 30 11:31 main.c
-rw-rw-r-- 1 hb hb   56 Jan 30 12:07 sub.h
-rw-rw-r-- 1 hb hb 1240 Jan 30 11:25 sub.o
[hb@VM-8-9-centos ~]$ gcc main.c add.o sub.o 
[hb@VM-8-9-centos ~]$ ./a.out 
Add(10, 20)=30
Sub(100,20)=80

所以如果我们不想给对方我们的源代码,我们可以给对方提供.o(方法的实现)和.h(都有什么方法)。但是如果方法有很多怎么办,写起来很不方便。我们可以将所有的.o文件打一个包给对方提供一个库文件即可,其实库的本质就是.o文件的集合。根据打包工具和打包方式的不同就将库分为静态库和动态库两类。

1.生成静态库

生成静态库操作:

[root@localhost linux]# ar -rc libmymath.a add.o sub.o

ar是gnu归档工具,ar是archives归档的前两个英文字母,rc表示(replace and create)
查看静态库中的目录列表。

[root@localhost linux]# ar -tv libmymath.a
rw-r--r-- 0/0 1240 Sep 15 16:53 2017 add.o
rw-r--r-- 0/0 1240 Sep 15 16:53 2017 sub.o

t:列出静态库中的文件
v:verbose 详细信息

[hb@VM-8-9-centos ~]$ ll
total 28
-rw-rw-r-- 1 hb hb 2688 Jan 30 13:04 libmymath.a
-rw-rw-r-- 1 hb hb  222 Jan 30 17:06 main.c
[hb@VM-8-9-centos ~]$ gcc main.c -I mytest/ -L . -l mymath
选项和路径以及名称之间的空格可有可无
[hb@VM-8-9-centos ~]$ gcc main.c -Imytest/ -L. -lmymath

-I:头文件路径,后面不需要跟头文件名,指定在哪个目录下即可。因为根据main.c中包含的头文件名会自动匹配对应的头文件。

编译器在搜索头文件时:
一在当前目录下搜索;
二在我们对应的系统默认指定路径上搜索。

-L:库的路径。
-l:库的名称,需要注意库名称是去掉前缀lib和.a的部分叫做库名;第三方库编译器不会自动匹配,所以第三方库除了-L指明库路径之外还需要指明库名称。
测试目标文件生成后,静态库删掉,程序照样可以运行。

我们用gcc和g++的时候却没有向上面一样指明头文件和库,原因是gcc和g++分别是编译c和c++的工具,用他们的标准库的时候会自动帮我们匹配头文件和库。而且gcc默认是动态链接的(建议行为),对于特定的一个库,究竟是动,还是静,取决于你提供的是动态库还是静态库!如果动态库占一部分,静态库占一部分,那么就整体按动态库来看待。
在这里插入图片描述

推荐阅读:gcc -I -L -l区别

闲写的太麻烦,也想像gcc编译普通程序那样,不带头文件和库名称有什么方法呢?
可以把头文件和库名称拷贝(拷贝相当于安装)到默认的搜索路径下:
[hb@VM-8-9-centos mytest]$ sudo cp *.h /usr/include/
[hb@VM-8-9-centos ~]$ sudo cp libmymath.a /usr/lib64
但是运行的时候需要带上库名称,还是因为mymath属于第三方库
[hb@VM-8-9-centos ~]$ gcc main.c -l mymath
一般不建议直接把自己写的库安装在系统默认路径下。

静态链接:

静态链接就是在装载之前,就完成所有的符号引用的一种链接方式。静态链接的处理过程分为2个步骤:
1、空间与地址的分配。扫描所有的目标文件,合并相似段,收集当中所有的符号信息。
2、符号解析与重定位。调整代码位置。

静态链接的优缺点

优点: 简单
缺点:
1、浪费内存空间。在多进程的操作系统下,同一时间,内存中可能存在多个相同的公共库函数。

补充:假如一个printf函数,多个程序都调用printf函数,通过静态链接形成的可执行程序运行的时候os会为它会产生PCB,进而和进程地址空间又有关系了,这几个可执行程序的代码区会有相同的部分。
2、只要有一个库模块更新,那么就需要重新编译打包整个代码。

2.生成动态库

shared: 表示生成共享库格式
fPIC:产生与位置无关码(position independent code)
库名规则:libxxx.so

[hb@VM-8-9-centos mytest]$ gcc -fPIC -c sub.c add.c 
[hb@VM-8-9-centos mytest]$ gcc -shared -o libmymath.so *.o 
[hb@VM-8-9-centos mytest]$ ls
add.c  add.h  add.o  libmymath.so  main.c  sub.c  sub.h  sub.o
[hb@VM-8-9-centos ~]$ ll
total 28
-rw-rw-r-- 1 hb hb   56 Jan 30 18:51 add.h
-rw-rw-r-- 1 hb hb  222 Jan 30 17:06 main.c
-rwxrwxr-x 1 hb hb 8432 Jan 30 20:31 myproc
drwxrwxr-x 2 hb hb 4096 Jan 30 18:45 mytest
-rw-rw-r-- 1 hb hb   56 Jan 30 18:51 sub.h

[hb@VM-8-9-centos ~]$ gcc -o myproc main.c -I . -L ./mytest/ -l mymath

[hb@VM-8-9-centos ~]$ ./myproc 
./myproc: error while loading shared libraries: libmymath.so: cannot open shared object file: No such file or directory

程序可以编译,但是运行不了,从运行结果可以看出,这里只在编译的时候告诉动态库在哪里,但是运行的时候从默认的搜索路径就找不到动态库了(为什么运行的时候要找动态库呢?因为一开始就说到动态库是程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码),那么怎么解决?

如何运行动态库?

1、拷贝.so文件 或者 .so文件的软硬链接到系统共享库路径下, 一般指/usr/lib
2、更改环境变量LD_LIBRARY_PATH
LD_LIBRARY_PATH作用:用于指定查找共享库(动态链接库)时除了默认路径(./lib和./usr/lib)之外的其他路径。

[hb@VM-8-9-centos mytest]$ echo $LD_LIBRARY_PATH 
:/home/hb/.VimForCpp/vim/bundle/YCM.so/el7.x86_64
//把带有动态库的路径添加到这个环境变量中。
[hb@VM-8-9-centos mytest]$ [hb@VM-8-9-centos mytest]$ export LD_LIBRARY_PATH=:/home/hb/.VimForCpp/vim/bundle/YCM.so/el7.x86_64:/home/hb/mytest
[hb@VM-8-9-centos mytest]$ gcc main.c -lmymath
//现在就可以运行了
[hb@VM-8-9-centos mytest]$ ./a.out
add(10, 20)=30
sub(100, 20)=80

但是这样下次再重新登录Linux的时候上次配置的环境变量就会失效。

3、配置/etc/ld.so.conf.d/,ldconfig更新
随便新建一个配置文件,就拿hb.conf为例,把将/home/hb/mytest通过vim写入到hb.conf配置文件里(注意普通用户需要用sudo提权,否则无法写入成功),然后通过ldconfig更新一下配置(注意普通用户需要用sudo提权),程序就可以运行了,而且下一次重新登录Linux不会失效。

[hb@VM-8-9-centos ld.so.conf.d]$ sudo vim hb.conf
[hb@VM-8-9-centos ld.so.conf.d]$ cat hb.conf 
/home/hb/mytest
[hb@VM-8-9-centos ld.so.conf.d]$ sudo ldconfig 

4、在把 动态库 或者 动态库的软硬链接 直接复制到当前目录下。

动态链接:

基本思想就是将对符号的重定位推迟到程序运行时才进行。推迟到运行时进行符号的重定位,就能解决静态链接的两个缺点。

对于第一个缺点:在运行时重定位,如果在运行过程中调用了公共库函数或者其他模块的函数,系统只需要在内存中维护一份公共库代码(具体在进程地址空间中的共享区)即可,只要将不同应用程序对公共库函数的调用地址设置成相同即可。

对于第二个缺点:理论上只要将需要替换的模块更新,无需将整个应用程序打包。

动态库的加载过程:

在这里插入图片描述
如图,对于动态链接来说,可执行程序中存放的是动态库中某具体 .o 文件的地址,同时,由于组成动态库的可重定向文件是通过fPIC生成的位置无关码,所以这个地址并不是 .o 文件的真正地址,而是该 .o 文件在动态库中的偏移量

接下来程序运行的时候,操作系统会将磁盘中的可执行程序加载到物理内存中,然后创建进程PCB,开始执行代码,当执行到库函数printf时,操作系统发现该函数链接的是一个动态库的地址,该地址是一个外部地址,操作系统就会暂停程序的运行,开始加载动态库。

然后操作系统会将磁盘中动态库加载到物理内存中,然后通过页表将其映射到该进程的地址空间的共享区中,os根据该动态库在地址空间中的地址(动态库的起始地址),以及库函数中存放的地址( .o文件在动态库中的偏移量),跳转到共享区中执行函数,执行完毕后跳转回来继续执行代码段后面的代码。这就是完整的动态库的加载过程。

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

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

相关文章

若依配置教程(二)集成积木报表JimuReport

积木报表配置官网 在搭建好若依环境成功运行以后&#xff0c;我们先在这个系统中加一个小功能&#xff1a;JimuReport积木报表&#xff0c;以下步骤&#xff0c;我们按照官网教程&#xff0c;详细配置一下&#xff1a; 1.在ruoyi-admin文件夹下的pom.xml加入jar包依赖&#x…

MLP多层感知机理解

目录 .1简介 .2例子 2.1模型 2.2 实例 2.2.1 问题描述 2.2.2 数学过程 .3 代码 3.1 问题描述 3.2 代码 references&#xff1a; .1简介 多层感知机是全连接的 可以把低维的向量映射到高维度 MLP整个模型就是这样子的&#xff0c;上面说的这个三层的MLP用公式总结起来…

C 语言零基础入门教程(二十)

C 预处理器 C 预处理器不是编译器的组成部分&#xff0c;但是它是编译过程中一个单独的步骤。简言之&#xff0c;C 预处理器只不过是一个文本替换工具而已&#xff0c;它们会指示编译器在实际编译之前完成所需的预处理。我们将把 C 预处理器&#xff08;C Preprocessor&#x…

练手好福利!20个Python实战项目含源代码【2023最新】

高效学习源代码的步骤&#xff1a;1.运行程序&#xff0c;观察表现2.运行源码&#xff0c;断点调试&#xff0c;从头跟一边源码的执行流程&#xff0c;注意函数堆栈3.画类图、流程图&#xff0c;先把遇到的重要类记录下来&#xff0c;表明各个类的关系4.记录问题&#xff0c;把…

Unity XR

一、几个Unity XR Interaction Toolkit学习地址 1.B站视频 https://www.bilibili.com/video/BV11q4y1b74z/?spm_id_from333.999.0.0&vd_source8125d294022d2e63a58dfd228a7fcf63 https://www.bilibili.com/video/BV13b4y177J4/?spm_id_from333.999.0.0&vd_source8…

【对象的比较】java代码实现,详解对象的比较,Comparable接口和Comparator比较器

前言&#xff1a; 大家好&#xff0c;我是良辰丫&#xff0c;&#x1f49e;&#x1f49e;&#x1f49e;今天的我们要学习的知识点是java对象的比较&#xff0c;不是大家现实生活中对象的比较&#xff0c;是java中new一个对象的那个对象&#xff0c;对象的比较到底是什么意思呢&…

24.网络编程(二)

目录 三.TCP通信 3.1 TCP协议特点 3.2 TCP协议通信场景 3.3 TCP通信模型演示 3.4 Socket 3.5 ServerSocket 3.6 注意事项 3.7 案例 3.7.1 TCP通信—单发单收 3.7.2 TCP通信—多发多收 3.7.3 TCP通信—同时接收多个客户端的消息。 3.7.4 TCP通信—使用线程池优化&am…

工业相机和镜头

工业相机和镜头镜头型号数据电源接口定焦镜头的调焦景深景深大小光圈相机、镜头选取参考镜头型号、数据电源接口、定焦镜头的调焦、景深、景深大小、光圈、相机、镜头选取 镜头型号 C&#xff0c;CS系列&#xff1a;相机镜头的C、CS接口非常相似&#xff0c;它们的接口直径、螺…

检索业务:基本数据渲染和排错

采用标签显示商品的数据 <div class"rig_tab"><div th:each"product:${result.getProducts()}"><div class"ico"><i class"iconfont icon-weiguanzhu"></i><a href"/static/search/#">…

5、数据的重构

目录 一、为什么进行数据重构 二、如何进行数据重构 一、为什么进行数据重构 进行数据分析时&#xff0c;有可能会发现数据的结构并不适合直接进行数据分析操作&#xff0c;如下面数据&#xff0c;但通过复制-粘贴-转置等方法操作又太繁琐&#xff0c;数据量小还行&#xff…

C++ 图进阶系列之 kruskal 和 Prim 算法_图向最小生成树的华丽转身

1. 前言 树和图形状相似&#xff0c;也有差异性。树中添加一条或多条边&#xff0c;可成图。图中减小一条或多条边&#xff0c;可成树。形态的变化由数据之间的逻辑关系决定。 图用来描述数据之间多对多关系。树用来描述数据之间一对多关系。 思考如下问题&#xff1f; 如果…

esp32 烧录协议

esp32的rom固化了出场固件。进入烧录模式后&#xff0c;esp32串口输出&#xff1a;给esp32烧录固件的时候&#xff0c;需要和rom的bootloder进行通讯。通讯时&#xff0c;使用 SLIP 数据包帧进行双向数据传输。每个 SLIP 数据包都以 0xC0 开始和结束。 在数据包中&#xff0c;所…

9、Servlet——Request对象

目录 一、get请求和post请求的区别 二、Request对象的应用 1、request主要方法 2、request获取数据 3、设置请求的编码格式 三、解决get请求收参乱码问题 四、解决post请求中文乱码问题 一、get请求和post请求的区别 在Servlet中用来处理客户端请求需要用doGet()方法或…

openGauss数据库源码解析系列文章——备份恢复机制:openGauss全量备份技术

目录 10.1 openGauss全量备份技术 10.1.1 gs_basebackup备份工具 10.1.2 gs_basebackup备份交互流程 本文主要介绍openGauss的备份恢复原理和技术。备份恢复是数据库日常维护的一个例行活动&#xff0c;通过把数据库数据备份到另外一个地方&#xff0c;可以抵御介质类的损…

数据结构与算法-稀疏数组

Java高级系列文章前言 本文章涉及到数据结构与算法的知识&#xff0c;该知识属于Java高级阶段&#xff0c;通常为学习的二阶段&#xff0c;本系列文章涉及到的内容如下&#xff08;橙色框选内容&#xff09;&#xff1a; 本文章核心是教学视频&#xff0c;所以属于个人笔记&a…

深度卷积对抗神经网络 基础 第六部分 缺点和偏见 GANs Disadvantages and Bias

深度卷积对抗神经网络 基础 第六部分 缺点和偏见 GANs Disadvantages and Bias GANs 综合评估 生成对抗网络&#xff08;英语&#xff1a;Generative Adversarial Network&#xff0c;简称GAN&#xff09;是非监督式学习的一种方法&#xff0c;透过两个神经网络相互博弈的方式…

实体对齐(三):RNM

一.摘要 实体对齐旨在将来自不同知识图&#xff08;KG&#xff09;的具有相同含义的实体联系起来&#xff0c;这是知识融合的重要步骤。 现有研究侧重于通过利用知识图谱的结构信息学习实体嵌入来进行实体对齐。这些方法可以聚合来自相邻节点的信息&#xff0c;但也可能带来来…

从软件开发角度看待PCI和PCIe

从软件开发角度看待PCI和PCIe 文章目录从软件开发角度看待PCI和PCIe参考资料&#xff1a;一、 最容易访问的设备是什么二、 地址空间的概念三、 理解PCI和PCIE的关键3.1 地址空间转换3.2 PCI接口速览3.3 PCIe接口速览四、 访问PCI/PCIe设备的流程4.1 PCI/PCIe设备的配置信息4.2…

特斯拉2022全年财报摘要

重点一览一、盈利方面 2022全年营业利润率为16.8%&#xff0c;其中第四季度为16.0% 2022全年GAAP营业利润为137亿美元&#xff0c;其中第四季度为39亿美元 2022全年GAAP净利润为126亿美元&#xff0c;其中第四季度为37亿美元 2022全年非GAAP净利润为141亿美元&#xff0c;其中…

MySQL中的多表联合查询

目录 一.介绍 数据准备 交叉连接查询 内连接查询 外连接 子查询 特点 子查询关键字 all关键字 any关键字和some关键字 in关键字 exists关键字 自关联查询 总结 一.介绍 多表查询就是同时查询两个或两个以上的表&#xff0c;因为有的时候用户在查看数据的时候,需要…