文件系统(软硬链接 动静态库 动态库加载的过程)

文章目录

  • 软硬链接
    • 软链接
      • 软链接有什么用?
    • 硬链接
      • 硬链接有什么用?
  • 动静态库
    • Linux中的动静态库
    • 静态库 && 安装库
    • 动态库
    • 动态库 VS 静态库
    • 用第三方库
  • 动态库加载
    • elf头部信息

软硬链接

先看现象:先创建一个文件,并写入内容
在这里插入图片描述
建立软链接:

ln -s file_target1.txt file_soft.link

在这里插入图片描述
inode不一样,所以都是独立的文件:
在这里插入图片描述
建立硬链接:

ln file_target2.txt file_hard.link

在这里插入图片描述
发现硬链接的inode一样,且中间的数字为2
在这里插入图片描述
总结特征:
1.软链接是一个独立的文件,因为有独立的inode number
2.硬链接不是一个独立的文件,因为没有独立的inode number,用的是目标文件的inode
3.属性中有一列硬链接数。

软链接

软连接的内容:目标所指的路径
这跟windows下的快捷方式一样:
在这里插入图片描述
用路径也可以运行
在这里插入图片描述
把目标文件删掉后,软链接也跑不起来了
在这里插入图片描述

软链接有什么用?

路径比较多的话,可以迅速找到一个文件
这里的myls是ls的软链接,可以运行./myls运行ls
在这里插入图片描述
平常使用的各种库就是软链接
在这里插入图片描述
综上所述:与windows的快捷方式相似

硬链接

先看现象:会发现这个数字就是引用计数(磁盘级的引用计数:有多少个文件名字符串指向同一个inode)
在这里插入图片描述
根据inode一样可知:硬链接就是在指定的目录下,添加一个新的文件名与inode number的映射!(跟指针差不多,两个指针指向同一块空间)

硬链接有什么用?

为什么新创建的目录文件的引用计数是2、普通文件的引用计数是1呢?
在这里插入图片描述
每个目录文件里面都有".“和”. ."
一个".“指向当前路径,发现dir中的”.“的inode和dir目录本身的inode一样
在这里插入图片描述
在dir中创建一个文件,发现引用计数变成了3:dir本身,dir目录下的”.“,otherdir目录下的”. ."
在这里插入图片描述
这就是为什么cd . . 就是返回上级路径
看现象:发现Linux系统中,不能给目录建立硬链接
在这里插入图片描述
原因:root.hard就是"/"
在这里插入图片描述
Linux可以给自己建立硬链接,因为".“与”. .“名字是固定内置好的。(删不掉”.“与”. .“,是因为系统维护好的)
还有一个作用:备份。先建立硬链接,后删除源文件,但依旧能访问到源文件的内容(跟某软件删不掉的原理相似)
在这里插入图片描述
综上所述,硬链接的作用是:
1.构建Linux的路径结构,让我们可以使用”.“和”. ."来进行路径定位
2.一般用硬链接来做文件备份

动静态库

我们常用的都是C、C++的标准库:strcpy、string、STL…这些函数或类必须有实现
在这里插入图片描述
ldd可以看见所调用的库
在这里插入图片描述
查看C标准库就是软链接
在这里插入图片描述
一个程序运行不仅需要二进制可执行文件(a.out),还需要库。

Linux中的动静态库

Linux中 .so(动态库) .a(静态库)
windows中 .dll(动态库) .lib(静态库)
Linux中的指令基本都是C语言写的,都用一个C语言库
在这里插入图片描述

以下面两个所写的库为例子
mymath.h

#pragma onceint Add(int,int);
int Sub(int,int);

mymath.c

#include "mymath.h"int Add(int x,int y)
{return x+y;
}int Sub(int x,int y)
{return x-y;
}

下面两个是在fopen、fwrite、fclose、fflush简易版库
mystdio.h

#pragma once#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>#define uint32_t unsigned int
#define LINE_SIZE 1024  //缓冲区大小
//124是标记位
#define FLUSH_NOW 1  //直接刷新
#define FLUSH_LINE 2  //行刷新
#define FLUSH_FULL 4  //全缓冲struct _myFILE
{uint32_t flags; //标记位int fileno;//缓冲区char cache[LINE_SIZE];int cap;  //容量大小int pos;  //下次写的位置
};typedef struct _myFILE myFILE;myFILE* my_fopen(const char* path,const char* flag);ssize_t my_fwrite(myFILE* fp,const char* data,int len);
void my_fflush(myFILE* fp);
void my_fclose(myFILE* fp);

mystdio.c

#include "mystdio.h"myFILE* my_fopen(const char* path,const char* flag)
{int flag1 = 0;int iscreate = 0; //  是否要创建文件mode_t mode = 0666;  //  权限if(strcmp(flag,"r") == 0){flag1 = (O_RDONLY);}else if(strcmp(flag,"w") == 0){flag1 = (O_WRONLY | O_CREAT | O_TRUNC);iscreate = 1; //需要创建文件}else if(strcmp(flag,"a") == 0){flag1 = (O_WRONLY | O_CREAT | O_APPEND);iscreate = 1; //需要创建文件}int fd = 0;if(iscreate)fd = open(path,flag1,mode);elsefd = open(path,flag1);if(fd < 0)  return NULL;myFILE* fp = (myFILE*)malloc(sizeof(myFILE));if(!fp)  return NULL;fp->flags = FLUSH_LINE;fp->fileno = fd;fp->cap = LINE_SIZE;fp->pos = 0;return fp;
}ssize_t my_fwrite(myFILE* fp,const char* data,int len)  //ssize_t->有符号整数
{memcpy(fp->cache+fp->pos,data,len);  //假设直接拷贝成功fp->pos+=len;if((fp->flags&FLUSH_LINE)&&fp->cache[fp->pos-1] == '\n'){write(fp->fileno,fp->cache,fp->pos);fp->pos = 0;}return len;
}void my_fflush(myFILE* fp)
{write(fp->fileno,fp->cache,fp->pos);fp->pos = 0;
}

在这里插入图片描述
以一个故事为线:
老师布置了一个写库的作业,你已经写完了,舍友不会想要你的源代码。
你:因为命名风格一样,老师可能发现抄袭,所以你直接把所有文件编成.o(所有方法的实现),发给舍友。
默认形成同文件.o

gcc -c [文件名.c]  

在这里插入图片描述
你舍友表示不会用,.o全是二进制文件,不知道如何用。于是你就把头文件给发过去了。头文件中包含着所有的函数声明。
在这里插入图片描述
但是你舍友还是不会用。
你:实现在.o里,.h跟实现手册一样。
于是又根据.h的方法写了main.c

#include "mymath.h"
#include "mystdio.h"
#include <stdio.h>
#include <string.h>int main()
{int a = 10;int b = 20;printf("%d+%d=%d\n",a,b,Add(a,b));myFILE* fp = my_fopen("./myfile.txt","w");if(fp == NULL)  return 1;const char* message = "hello Linux\n";my_fwrite(fp,message,strlen(message));my_fclose(fp);return 0;
}

发现报错信息是没有找到函数实现,因为只编译了你的文件,舍友的文件没有被编译
在这里插入图片描述
把main.c->main.o
在这里插入图片描述
总结:头文件是一个手册,提供函数的声明,告诉用户怎么用。.o提供实现,我们只需要补上一个main,调用头文件提供的方法,然后和.o进行链接,就能形成可执行
故事进入第二阶段:
老师看你和你的舍友能力挺强,于是安排新任务,需要写100个源文件。
于是你故技重施,把100个.o发给舍友,然后舍友误删了几个,编不过了。
可以打包一起发送,但是舍友不会解包。你说行吧,用ar命令
r是replace,c是create,相当于把所有的.o文件打包,并且舍友不需要解包。

ar -rc [文件名].a *.o

在这里插入图片描述
可以直接编译,因为系统自动帮助你把main.c->main.o。
在这里插入图片描述
综上所述:所谓的库就是打包*.o
库的作用:提高开发效率。(你舍友只拿着函数说明书就能运行,不用自己编写源代码)

静态库 && 安装库

依旧使用ar命令,ar是gnu归档工具

ar -rc [文件名].a [文件名].o

故事进入第三阶段:
把.h文件放进include中,把.a文件放进lib中
在这里插入图片描述
给舍友发过去了lib,舍友想直接用这个库,需要安装到系统里(只需要把头文件拷贝到头文件的搜索里,.a文件也是一样)。

sudo cp mylib/include/*.h /usr/include/
sudo cp mylib/lib/*.a /lib64

在这里插入图片描述
安装后,就跟下载的安装包类似,发给舍友的lib可以不要了
这样头文件可以用<>

#include <mymath.h>
#include <mystdio.h>

发现依旧找不到函数
在这里插入图片描述
因为我们平常使用的是C/C++的库,gcc/g++默认是认识C/C++库。
libmyc.a --》别人写的(第三方库) --》gcc/g++不认识 --》> -l[库名] 表示链接某库
发现找不到库(-l后面可以带空格 -l libmyc.a)
在这里插入图片描述
依旧找不到库,gcc认为去前缀,去掉后缀,剩下来的才是库的名字
在这里插入图片描述
这样就可以运行了。
在这里插入图片描述
以上就完成了库的安装,不推荐把自己的库放进去。因为可能会污染库。
不安装,如何用库呢?
因为main.c与.h和.a不处在同一路径下,所以.c文件找不到.h和.a文件
在这里插入图片描述
-I是include的意思(这里是大写的i),程序员自己指定头文件的路径。
gcc也是进程,在运行的时候,pwd拼上后面的路径,找到了头文件所在地

gcc [文件名].c -I [路径]

运行不了,链接报错
在这里插入图片描述
gcc表示我只认系统默认的库文件/lib64 /usr/lib64,你的库(第三方的库)在哪不知道
-L是lib的意思,告诉gcc我的库在哪

gcc [文件名].c -I [路径] -L [路径]

还是链接报错
在这里插入图片描述
因为还没有告诉gcc你要找哪个库,就跟/lib64目录下有很多库,你得告诉gcc找哪个库
在这里插入图片描述
库名依旧是去掉前缀和后缀

gcc [文件名].c -I [路径] -L [路径] -l[库名]

在这里插入图片描述
总结:
在这里插入图片描述
问题来了:
头文件为什么不用指定具体名称?
头文件已经指定了,你的.c文件里面指定的
在这里插入图片描述
不指明-I也可以在.c文件里指明
注意<>表示在系统的路径下去找,现在要在当前的路径下找所以得用""

#include "mylib/include/mymath.h"
#include "mylib/include/mystdio.h"

在这里插入图片描述
还有一个问题:我们用的libmyc.a库,为什么没有显示出来?
在这里插入图片描述
编译时只指明静态库(libmy.c)时,形成可执行程序时能动态链接的就动态链接,只能静态链接的,就把实现拷贝到可执行程序(a.out)中。
-static的表示全部强制静态链接
在这里插入图片描述

动态库

想要实现动态库要加个选项fPIC

gcc -fPIC -c 文件名.c

动态库在发开中用的最频繁的,编译器自己支持形成动态库,直接使用gcc/g++

gcc *.o -o [库名].so

报错了,因为库中不能存在main函数
在这里插入图片描述
告诉gcc我要形成动态库:-shared

gcc -shared *.o -o [库名].so

在这里插入图片描述
也把动态库拷贝到库中
在这里插入图片描述

gcc main.c -I mylib/include/ -L mylib/lib -l myc

编译能编过,但是无法运行。
在这里插入图片描述
发现libmyc.so找不到
在这里插入图片描述
因为只告诉了gcc/g++,形成a.out是gcc的工作。但没有告诉操作系统,./a.out运行操作系统不知道库在哪。
综上:
动态库:动态库要在程序运行的时候,要找到动态库加载并运行!
静态库:编译期间,已经将库中的代码拷贝到我们的可执行程序的内部了!加载和库就没有关系了!
系统默认在/lib64下寻找,链接和运行时都在/lib64下寻找。
第一种方法:把动态库拷贝到/lib64路径下(不建议)
在这里插入图片描述
第二种方法:在/lib64中建立一个软链接
在这里插入图片描述
第三种:操作系统中有个环境变量LD_LIBRARY_PATH,其中存储的就是动态库的搜索路径(不推荐)

echo $LD_LIBRARY_PATH

在这里插入图片描述

LD_LIBRARY_PATH=$LD_LIBRARY_PATH:[需要添加的路径]

在这里插入图片描述
在这里插入图片描述
第四种:ld的意思为Load,so的意思是库,conf的意思是配置文件,.d的意思是目录

ls /etc/ld.so.conf.d

这个目录当中存储的是在系统当中的配置文件。
在这里插入图片描述
把当前要用的库的路径添加到其中,就永久生效了
首先是root才能修改
在这里插入图片描述
其次在目录中命名一个文件,命名必须要以.conf结尾
在这里插入图片描述
再把路径写入其中
在这里插入图片描述
在root的权限下让配置文件生效:

ldconfig

就可以运行了
在这里插入图片描述

动态库 VS 静态库

动静态库的大小差很多
在这里插入图片描述
-static 的意义是强制将我们的程序静态链接,这就要求我们链接的任何库都必须提供对应的静态库版本。

用第三方库

用别的人库,应该提供什么呢?

sudo yum install ncurses

下载开发版本:

sudo yum install ncurses-devel

在这里插入图片描述
下面的代码具体在这个网址C语言实现简易文本编辑器(新手向)

#include <ncurses.h>
int main(){int key=0;initscr();noecho();keypad(stdscr,TRUE);key=getch();while(key!='$'){printw("%d\n",key);key=getch();refresh();}endwin();
}

因为是第三方库,所以编译使用命令时需要链接

gcc test.c -l ncurses

在这里插入图片描述

动态库加载

下面是调用动态库的简略版过程。
动态库被加载之后,要映射到当前进程的堆栈之间的共享区。
在这里插入图片描述
如果其他进程也需要该动态库,是不用重复加载的,都用这一份动态库。也称共享库
在这里插入图片描述
执行可执行程序,编译成功,没有加载运行时,二进制代码中有"地址"吗?
看现象:

#include <stdio.h>int Sum(int top)
{int i = 1;int ret = 0;for(;i<=top;i++){ret += 1;}return ret;
}int main()
{int top = 100;int result = Sum(top);printf("result:%d\n",result);return 0;
}

看反汇编

objdump -S a.out > code.s

可以看出是有地址的。函数名也变成了地址
在这里插入图片描述
在可执行形成的时候,也规划好了地址所用的空间
在这里插入图片描述
Linux中的可执行程序都是ELF格式的可执行程序,形成的二进制时是有自己的固定格式的。固定格式中有elf可执行程序的头部,里面有很多可执行程序的属性。
在这里插入图片描述
如何编制呢?
假设编址范围是0000 0000 ~ FFFF FFFF (虚拟地址,又称为逻辑地址)
地址种类:绝对编址(从0000 0000依次往后排) 又称为平坦模式。上图就是绝对编址
相对编址:相对地址+偏移量 (所有函数的起始地址都为0,里面存的都是偏移量0,1,2…)
在这里插入图片描述

elf头部信息

下图画红线的是Linux中的加载器:先让操作系统把库加载到内存中,执行库里面的方法,把可执行程序拷贝到内存中。拷贝时有虚拟地址。程序中有头部信息,一定要被加载器进行解释、扫描代码、找到main的入口,并且在elf头文件中加载各个区(程序被划分各个区的)。
在这里插入图片描述
ELF+加载器:可以让我们找到各个区域区域的起始和结束地址与main函数的入口地址
第二个问题:
进程 = 内核数据结构 + 代码和数据。先有内核数据结构后再有代码和数据添加到内存中。mm_struct 是结构体对象,成员变量是由code_start、code_end…组成,那么成员变量的初始值从哪里来呢?
首先肯定不是操作系统固定规划的,你写了一个正文5行的hello world,他写了50w行的CSGO,正文段的结束肯定不一样。
只有可执行程序自己知道有多大,在elf头部信息中有代码段多大的信息,填入到mm_struct中。
综上:虚拟地址空间由OS、编译器、加载器共同组成。
故事:你在学校的宿舍比如是513的2号床(物理地址),学号是111(虚拟地址),线下找你肯定是拿着宿舍的地址找你,校方线上查看档案肯定是拿着学号找。所以你在学校有你的学号(虚拟地址),占有宿舍空间(物理地址),形成了映射关系。
CPU存在一个寄存器:pc指针,会保存要执行下一条指令的地址。(pc指向哪里,CPU就要执行哪里的代码)
在这里插入图片描述
CPU开始运行:CPU问pc指针我接下来要运行哪条指令。pc指针给出地址,因为是虚拟地址要根据进程查页表,然后找到了真实的物理地址去运行,同时把下一条指令的虚拟地址读到pc指针中,重复上述过程。
在这里插入图片描述
库函数与上述可执行文件的编址也一样,除了没有main函数
在这里插入图片描述
磁盘中的地址都是虚拟地址
在这里插入图片描述
只有物理地址是无法使用的,需要mm_struct中的栈和堆之间开辟一段空间(因为物理内存中已经有库了,所以开辟多少空间的大小也是确定的)填入库的虚拟地址,然后与页表建立映射关系。
在这里插入图片描述
假设虚拟地址是00000000~FFFFFFFF
在磁盘中,库中每一个函数都可以表示为myc:偏移量(lib库的地址+偏移量)
在这里插入图片描述
磁盘中的偏移量,加载到mm_struct中的偏移量是不变的。
在这里插入图片描述
综上:库被映射到地址的什么位置是不重要的,只要找到库的起始的地址,就能通过偏移量找到函数。
库函数调用,是在地址空间内来回调用。
上面说的库被加载进内存,那如何知道库有没有被加载呢?
首先我们要知道库不止一个,不止一个说明要管理,管理:先组织,再描述
在这里插入图片描述
内存中有一个描述库的结构体:什么时候被加载进去,谁映射的…
当有其他程序需要用到这个库的时候,遍历列表发现其有没有被加载,有加载直接映射。
总结动态库加载的过程:可执行程序先加载内存中,运行到需要调用库的地方,如果库不在,就缺页中断,根据路径找到库加载进来,通过映射得到我的库的起始地址,库的地址+偏移量找到方法(函数)。
静态库直接放进正文代码中。
-fPIC表示:让动态库独立加载,不和可执行程序拷贝在一起。在物理地址中任意加载,在地址空间中任意映射

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

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

相关文章

ELK-01-elasticsearch-8.15.1安装

文章目录 前言一、下载elasticsearch二、将tar包放到服务器三、解压tar包四、更改配置文件五、添加启动用户六、用elasticserch用户启动6.1 报错6.2 解决问题16.3 解决问题26.4 再次用elasticserch用户启动6.5 windows浏览器打开 七、设置开机自动启动7.1 创建启动脚本7.2 在脚…

在Java中 String能存储多少个字符?

经典面试题 关于String能存储多个字符&#xff0c;这个是面试者在面试中经常被提及的问题&#xff0c;这个问题可以问的很浅&#xff0c;也可以问的很深&#xff0c;具体看面试官看了你的简历后&#xff0c;对你的能力有什么样的看法&#xff0c;今天&#xff0c;我们就这个问…

postman发送与返回,GET与POST使用

1.GET 获取主页 发送&#xff1a; uri: ‘/’ 返回&#xff1a; 2.POST 发送密码 发送&#xff1a; uri: ‘/login.html’ 返回&#xff1a; 3.POST 保存参数 发送&#xff1a; 返回&#xff1a; 4.GET 获取参数 在POST密码之后&#xff0c;服务器发送一个H…

西门子PCS7在CFC中如何连接DB块中的变量

在CFC中所连接的DB块必须是用户数据块(User DB)。在CFC中通过菜单Options Customize Compile/Download… 可以查看和修改用户数据块的范围&#xff0c;默认范围是DB1-DB60&#xff0c;超出该范围的DB块在CFC中无法引用&#xff0c;如果引用了&#xff0c;CFC编译时会提示错误。…

Linux复习--系统管理类(权限优化、备份策略、RAID、资源查看、启动流程、系统优化)

一、权限优化 1、文件的基本权限 以下知识点详细情况点击&#xff1a; Linux--用户身份和文件权限_linux用户文件权限-CSDN博客https://blog.csdn.net/lerp020321/article/details/140232127 1.1、文件身份 身份分类&#xff1a;所有者&#xff08;u&#xff09;、所属组&am…

C++ | Leetcode C++题解之第430题扁平化多级双向链表

题目&#xff1a; 题解&#xff1a; class Solution { public:Node* flatten(Node* head) {function<Node*(Node*)> dfs [&](Node* node) {Node* cur node;// 记录链表的最后一个节点Node* last nullptr;while (cur) {Node* next cur->next;// 如果有子节点…

golang学习笔记11-模块化与包管理【重要】

注&#xff1a;本人已有C&#xff0c;C,Python基础&#xff0c;只写本人认为的重点。 在第六节&#xff08;golang学习笔记6&#xff09;中&#xff0c;我讲了如何自定义包&#xff0c;包其实有两种引用方式&#xff0c;一种是不用模块&#xff0c;还有种是用模块&#xff0c;我…

Leetcode 543. 124. 二叉树的直径 树形dp C++实现

问题&#xff1a;Leetcode 543. 二叉树的直径&#xff08;边权型&#xff09; 给你一棵二叉树的根节点&#xff0c;返回该树的 直径 。 二叉树的 直径 是指树中任意两个节点之间最长路径的 长度 。这条路径可能经过也可能不经过根节点 root 。两节点之间路径的 长度 由它们之…

创新学生宿舍管理:Spring Boot框架实践

第2章 开发环境与技术 学生宿舍管理系统的编码实现需要搭建一定的环境和使用相应的技术&#xff0c;接下来的内容就是对学生宿舍管理系统用到的技术和工具进行介绍。 2.1 MYSQL数据库 本课题所开发的应用程序在数据操作方面是不可预知的&#xff0c;是经常变动的&#xff0c;没…

计算机前沿技术-人工智能算法-大语言模型-最新论文阅读-2024-09-20

计算机前沿技术-人工智能算法-大语言模型-最新论文阅读-2024-09-20 1. Multimodal Fusion with LLMs for Engagement Prediction in Natural Conversation Authors: Cheng Charles Ma, Kevin Hyekang Joo, Alexandria K. Vail, Sunreeta Bhattacharya, Alvaro Fern’andez Ga…

《汇编语言》第14章——实验 14访问CMOS RAM

编程&#xff0c;以“年/月/日 时&#xff1a;分&#xff1a;秒”的格式&#xff0c;显示当前的日期、时间 assume cs:code data segment db 2024/09/23 00:00:00,$ data endscode segment start:mov ax,datamov es,axcall get_hms_funccall get_ymd_funcmov dh,12 ;dh中存放…

Beyond 5.5旗舰版和高级版激光软件

Beyond 5.5旗舰版和高级版激光软件具有以下一些特点和功能&#xff1a; 1. 强大的功能特性&#xff1a; • 多媒体支持&#xff1a;它是真正的多媒体控制激光软件&#xff0c;除支持基本的激光图案外&#xff0c;还支持视频、3D 动画和绘图程序等&#xff0c;为用户提供了丰富…

Springcloud框架-能源管理系统-能源管理系统源码-能源在线监测平台-双碳平台

一、介绍 基于SpringCloud的能管管理系统-能源管理平台源码-能源在线监测平台-双碳平台源码-SpringCloud全家桶-能管管理系统源码 有需者咨询&#xff0c;非诚勿扰&#xff1b; 二、软件架构 二、功能介绍 三、数字大屏展示 四、数据采集原理 五、软件截图

Windows11系统安装,配置CUDA、cuDNN等

已经有大几年没有安装过 Windows 的系统了&#xff0c;今天因为黑神话悟空&#xff0c;准备把 Win 11 装一台&#xff0c;玩玩游戏&#xff0c;顺便把一些 CUDA 相关的异步解析项目也安装到 Window 上。 下载安装 PE 因为十几年前&#xff0c;只会用 PE 装系统&#xff0c;所…

XSS闯关小游戏(前13关)

挖掘思路 1.存在可控参数 2.页面存在回显 3.使用带有特殊字符的语句去测试&#xff0c;网站是否进行了实例化 ( 例如 ">123 ) 4.构造闭合&#xff0c;实现payload的逃逸 1 name处参数可控&#xff0c;直接打即可 2 这里知道<>被实体编码了 再测试">1…

DANN GRL

域自适应是指在目标域与源域的数据分布不同但任务相同下的迁移学习&#xff0c;从而将模型在源域上的良好性能迁移到目标域上&#xff0c;极大地缓解目标域标签缺失严重导致模型性能受损的问题。 介绍一篇经典工作 DANN &#xff1a; 模型结构 在训练阶段需要预测如下两个任务…

langchain的构成

1.简介 langchain的构成其包含langchain-core,langchain-community,langchain,langgraph,langserve,langSmith。 2&#xff0c;构件的详解 ‌LangChain Core‌ ‌LangChain Core‌是LangChain框架的核心组成部分&#xff0c;它包含了不同组件的基本抽象以及将它们组合在一起…

【每天学个新注解】Day 4 Lombok注解简解(三)—@NonNull

我们在之前的三天学了Lombok常用的注解&#xff1a; 【每天学个新注解】Day 1 Lombok注解简解&#xff08;〇&#xff09;—Getter、Setter、ToString、EqualsAndHashCode、Constructor 【每天学个新注解】Day 2 Lombok注解简解&#xff08;一&#xff09;—Data、Build、Value…

Kubernetes调度单位Pod

Kubernetes调度单位Pod 1 Pod简介 不直接操作容器container。 一个 pod 可包含一或多个容器&#xff08;container&#xff09;&#xff0c;它们共享一个 namespace&#xff08;用户&#xff0c;网络&#xff0c;存储等&#xff09;&#xff0c;其中进程之间通过 localhost 本地…

iOS 巨魔技巧:一键汉化巨魔商店

嘿&#xff0c;这是黑猫。iOS 巨魔商店一直都有个严重的问题&#xff1a;界面纯英文&#xff0c;不支持简体中文。 当然了&#xff0c;在IT行业&#xff0c;英语是通用语言。但是&#xff0c;既然巨魔/越狱面向普罗大众的技术&#xff0c;那么做好语言适配&#xff0c;还是很关…