哈工大2021~2022春季学期《计算机系统》大作业
计算机系统
大作业
题 目 程序人生-Hello’s P2P
专 业 计算机类
学 号 120L021025
班 级 2003001
学 生
指 导 教 师 史先俊
计算机科学与技术学院
2022年5月
2.2在Ubuntu下预处理的命令.......................................................................... - 7 -
3.2 在Ubuntu下编译的命令............................................................................. - 9 -
4.2 在Ubuntu下汇编的命令........................................................................... - 14 -
5.2 在Ubuntu下链接的命令........................................................................... - 20 -
5.3 可执行目标文件hello的格式.................................................................. - 20 -
5.5 链接的重定位过程分析............................................................................... - 26 -
6.2 简述壳Shell-bash的作用与处理流程..................................................... - 30 -
6.3 Hello的fork进程创建过程..................................................................... - 30 -
6.6 hello的异常与信号处理............................................................................ - 32 -
第7章 hello的存储管理............................................................................... - 33 -
7.1 hello的存储器地址空间............................................................................ - 33 -
7.2 Intel逻辑地址到线性地址的变换-段式管理............................................ - 33 -
7.3 Hello的线性地址到物理地址的变换-页式管理...................................... - 34 -
7.4 TLB与四级页表支持下的VA到PA的变换............................................. - 34 -
7.5 三级Cache支持下的物理内存访问.......................................................... - 35 -
7.6 hello进程fork时的内存映射................................................................... - 35-
7.7 hello进程execve时的内存映射............................................................... -36 -
7.8 缺页故障与缺页中断处理........................................................................... - 36 -
8.1 Linux的IO设备管理方法.......................................................................... - 38 -
8.2 简述Unix IO接口及其函数....................................................................... - 38 -
第1章 概述
1.1 Hello简介
1.2 环境与工具
主机:X64 CPU(i7-10750H);2.6 GHz;2×8G RAM;1T SSD;
虚拟机:X64 CPU(i7-10750H);2.6 GHz;4.0G RAM;20G SSD。
Linux:VMware Workstation 15 Pro;Ubuntu 64位-20.04。
Windows下:Visual Studio 2022,Dev-C++;CodeBlocks 20.03;
Linux下:CodeBlocks 20.03;gcc9.3.0/Linux。
1.3 中间结果
文件名 |
功能 |
hello.c |
源程序 |
hello.i |
预处理后得到的文本文件 |
hello.s |
编译后得到的汇编语言文件 |
hello.o |
汇编后得到的可重定位目标文件 |
hello |
链接后得到的可执行目标文件 |
hello.elf |
用readelf读取hello.o得到的ELF格式信息 |
hello_elf.txt |
用readelf读取hello得到的ELF格式信息 |
hello.asm |
反汇编hello.o得到的反汇编文件 |
hello2.asm |
反汇编hello可执行文件得到的反汇编文件 |
1.4 本章小结
第2章 预处理
2.1 预处理的概念与作用
2.1.2预处理的作用:预处理通过调用系统头文件,用实际内容替换用#define定义的字符串,简化了程序,使编译器编译程序时更加方便。
2.2在Ubuntu下预处理的命令
2.3 Hello的预处理结果解析
hello.c经预处理得到hello.i文件,hello.i共3060行,大小为64.7KB。
此后是所调用函数的声明,文件的最后是hello.c中的main()函数,它位于第3047到第3060行。
2.4 本章小结
本章介绍了预处理的概念、过程、作用、实现指令,并对预处理操作的结果进行了解析,展示了程序生命周期中的第一步。
第3章 编译
3.1 编译的概念与作用
编译将预处理后的文本文件转化为汇编语言文件,为把高级语言变成计算机可以识别的二进制语言的过程做准备。
3.2 在Ubuntu下编译的命令
3.3 Hello的编译结果解析
立即数1,4等直接转化为$1、$4,并直接使用,如第25行cmpl $4, %edi。
int i 作为局部变量被存储在寄存器或者栈空间中。i作为函数内部的局部变量,并不占用文件实际节的空间,只在运行时存在于栈中。对于i的操作就是直接对寄存器或栈进行操作。
int argc是main函数的第一个参数,64位编译下,argc由寄存器%rdi传入,进而保存在堆栈中。
字符串"用法: Hello 学号 姓名 秒数!\n"和"Hello %s %s\n"均被储存在.text数据段中,其中汉字采用UTF-8编码,每个汉字占3个字节。
char *argv[]是main函数的第二个参数。在hello.s中,其首地址保存在栈中。访问时,通过寄存器%rbx寻址的方式访问。图中%rsi储存argv[1],%rdi储存argv[2]。
对局部变量的赋值使用movx指令完成。如将局部循环变量i的值保存在寄存器%ebp中。
(不)等于判断及其跳转使用cmpx和jne指令实现。如if(argc!=4),若判断结果不相等,则CS:IP跳转到jne后地址的指令,若相等则继续顺序执行指令。
通过将首地址保存在栈中,并使用寄存器%rbx通过相对寻址的方式访问。
还有一些算数操作,如修改访问数组使用的寄存器等操作,同样通过addq和subq等指令实现。
(1)调用函数采用callq指令实现,执行这条指令后程序计数器CS:IP会被设置为callq后的地址。
(3)在函数执行开始时,可能需要为其局部变量分配空间,在返回前,又必须释放这些空间。
3.4 本章小结
第4章 汇编
4.1 汇编的概念与作用
4.1.1 概念:汇编是指汇编器(assembler)将以.s结尾的汇编程序翻译成机器语言指令,并把这些指令打包成可重定位目标程序格式,最终结果保存在.o 目标文件中的过程。
4.1.2 作用:将汇编语言翻译为机器指令,并将这些指令以可重定位目标程序格式保存在.o文件中。为后续的链接和执行过程奠基。
4.2 在Ubuntu下汇编的命令
Ubuntu下的汇编命令为gcc -m64 -no-pie -fno-PIC -c hello.s -o hello.o
4.3 可重定位目标elf格式
分析hello.o的ELF格式,用readelf等列出其各节的基本信息,特别是重定位项目分析。
生成ELF文件的指令为readelf -a hello.o > hello.elf
生成的ELF文件包括ELF头、节头、程序头(本文件无)、重定位节等内容。具体如下:
包含了文件中出现的各个节的详细信息,包括节的标号、类型、大小和位置(地址与偏移量)等信息。
.rela.text:是一个.text 节中位置的列表,包含.text 节中需要进行重定位的信息,当链接器把这个目标文件和其他文件组合时,需要修改这些位置。
偏移量 |
代表需要进行重定向的代码在.text或.data节中的偏移位置 |
信息 |
包括symbol和type两部分,其中symbol占前半部分,type占后半部分,symbol代表重定位到的目标在.symtab中的偏移量,type代表重定位的类型 |
类型 |
重定位到的目标的类型 |
符号名称+加数 |
计算重定位位置的辅助信息 |
符号表中保存着定位、重定位程序中符号定义和引用的信息,所有重定位需要引用的符号都在其中声明。
4.4 Hello.o的结果解析
生成hello.o的反汇编文件的指令为objdump -d -r hello.o。
对比两版本对hello.c源程序的转换,可以发现,反汇编文件的篇幅明显短于汇编文件,但对于具体的语句类型,汇编文件与反汇编文件几乎一致,不同点具体如下:
(1)格式上,hello.i前没有一串二进制数,即相应的机器码,而反汇编代码前面有与之对应的机器码。
(2)数据内容上,立即数在hello.i这一汇编语言文本文件中为十进制,而在反汇编代码中为十六进制。
(3)跳转方式不同。在汇编代码中,代码直接声明具体的段存储位置,通过助记符(如.L0、.L1等)存储在.rodata段中;而反汇编代码是依据地址跳转的。
(4)重定位条目不同。汇编代码仍然采用直接声明的方式,即通过助记符;而反汇编代码采用重定向的方式进行跳转,机器代码在此处留下一些地址以供链接时重定向。
4.5 本章小结
第5章 链接
5.1 链接的概念与作用
把可重定位目标文件和命令行参数作为输入,产生一个完全链接的,可以加载运行的可执行目标文件。使得分离编译成为可能。
5.2 在Ubuntu下链接的命令
5.3 可执行目标文件hello的格式
用readelf查看hello的ELF格式的命令为readelf -a hello > hello_elf.txt。
图5.2 用readelf查看hello的ELF格式的命令和结果
(2)节头:节头描述了26个节的相关信息,其中一些段的作用如下:
dynamic段:该段中保存了动态链接器所需要的基本信息,是一个结构数组,可以看做动态链接下 ELF文件的“文件头”。存储了动态链接会用到的各个表的位置等信息。
rel.dyn段:对数据引用的修正,其所修正的位置位于 “.got”以及数据段(类似重定位段 “rel.data”)
rel.plt段:对函数引用的修正,其所修正的位置位于 “.got.plt”。
(4)Section to Segment mapping:如图。
(6)重定位节:.rela.dyn和.rela.plt,如图。
5.4 hello的虚拟地址空间
如.interp段地址从0x4002e0开始,偏移量为0x2e0,大小为0x1c,对齐要求为1。
5.5 链接的重定位过程分析
使用objdump查看hello汇编语言的指令为objdump -d -r hello
(1)hello.o反汇编代码虚拟地址从0开始;而hello反汇编代码从0x400000开始。
(2)hello.o反汇编代码的第一个段是.text段,然后为main函数;而由于链接过程中重定位而添加进来了各种函数、数据,在hello反汇编的结果中开始的函数和调用的函数填充在main函数之前。
(3)call函数引用全局变量和跳转模块值时地址也有所变化。可执行文件跳转和应用就是相对或绝对的虚拟内存地址;而hello.o反汇编的跳转的就是只要hello数据时对应的位置。
5.6 hello的执行流程
程序名称 |
程序地址 |
ld-2.27.so!_dl_start |
0x7fce8cc38ea0 |
ld-2.27.so!_dl_init |
0x7fce8cc47630 |
hello!_start |
0x400500 |
libc-2.27.so!__libc_start_main |
0x7fce8c867ab0 |
-libc-2.27.so!__cxa_atexit |
0x7fce8c889430 |
-libc-2.27.so!__libc_csu_init |
0x4005c0 |
hello!_init |
0x400488 |
libc-2.27.so!_setjmp |
0x7fce8c884c10 |
-libc-2.27.so!_sigsetjmp |
0x7fce8c884b70 |
--libc-2.27.so!__sigjmp_save |
0x7fce8c884bd0 |
hello!main |
0x400532 |
hello!puts@plt |
0x4004b0 |
hello!exit@plt |
0x4004e0 |
*hello!printf@plt |
-- |
*hello!sleep@plt |
-- |
*hello!getchar@plt |
-- |
ld-2.27.so!_dl_runtime_resolve_xsave |
0x7fce8cc4e680 |
-ld-2.27.so!_dl_fixup |
0x7fce8cc46df0 |
--ld-2.27.so!_dl_lookup_symbol_x |
0x7fce8cc420b0 |
libc-2.27.so!exit |
0x7fce8c889128 |
5.7 Hello的动态链接分析
在dl_init调用之前,对于每一条PIC函数调用,调用的目标地址都实际指向PLT中的代码逻辑,初始时每个GOT条目都指向对应的PLT条目的第二条指令。
在dl_init调用之后,0x6008c0和0x6008c0处的两个8字节的数据分别发生改变。
5.8 本章小结
第6章 hello进程管理
6.1 进程的概念与作用
进程为我们塑造一种假象,我们的程序好像是当前唯一运行的程序,我们的程序好像独占CPU和内存,我们程序的代码和数据好像是系统内存中唯一的内容。
6.2 简述壳Shell-bash的作用与处理流程
(2)shell对用户输入命令进行解析,判断是否为内置命令;
(3)若为内置命令,调用内置命令处理函数,否则调用execve函数创建一个子进程进行运行。
(4)判断是否为前台运行程序,如果是,则调用等待函数等待前台作业结束;否则将程序转入后台,直接开始下一次用户输入命令。
(5)shell应该接受键盘输入信号,并对这些信号进行相应处理。
6.3 Hello的fork进程创建过程
当在shell上输入./hello时,由于这个不是一个内置的shell命令,所以shell会认为hello是一个可执行目标文件,通过调用某个驻留在存储器中被称为加载器的操作系统代码来运行它。
6.4 Hello的execve过程
execve函数加载并运行可执行文件filename(hello),且带参数列表argv和环境变量envp。只有当出现错误时,例如找不到filename,execve才会返回到调用程序。
6.5 Hello的进程执行
多个流并发地执行的一般现象被称为并发。一个进程和其他进轮流运行的概念称为多任务。一个进程执行它的控制流的一部分的每一时间段叫做时间片。因此,多任务也叫做时间分片。
操作系统内核使用一种称为上下文切换的较高层形式的异常控制流来实现多任务。内核为每个进程维持一个上下文。上下文就是内核重启一个被抢占的进程所需得状态。
在执行过程中,内核可以决定抢占当前进程,并重新开始一个先前被抢占的进程,这个决策称为调度。
hello程序与操作系统其他进程通过操作系统的调度,切换上下文,拥有各自的时间片从而实现并发运行。所以其实hello在sleep时就是这样的切换。
程序在进行一些操作时会发生内核与用户状态的不断转换。这是为了保持在适当的时候有足够的权限和不容易出现安全问题。
6.6 hello的异常与信号处理
(1)不停乱按:按下普通的字符,包括字母、数字、回车、空格等等并不影响程序运行。按下的内容会被立即输出到屏幕。
(2)按下ctrl+z会暂停进程,此时按下ps会列出当前系统中进程,标明进程名称和进程号。
(3)按下jobs会列出当前shell环境中已启动的任务状态。
6.7本章小结
shell接收用户输入的命令行,执行对应的内置命令或代表用户执行对应的可执行程序。程序运行被抽象为进程,每个进程运行在独立的进程上下文中,进程之间切换涉及进程切换的具体原理、细节。
shell执行程序的方式为构造要传递给execve函数的字符串组,fork子进程,并设置进程组id,然后调用execve函数,根据传入的字符串组复制可执行程序到内存执行。
程序执行可分为前台和后台执行两种。键盘输入信号可影响程序的执行,或查看当前shell中运行的各个进程信息。
第7章 hello的存储管理
7.1 hello的存储器地址空间
在有地址变换功能的计算机中,访问指令给出的地址 (操作数) 叫逻辑地址,也叫相对地址。要经过寻址方式的计算或变换才得到内存储器中的物理地址。
在存储器里以字节为单位存储信息,为正确地存放或取得信息,每一个字节单元给以一个唯一的存储器地址,称为物理地址,又叫实际地址或绝对地址。
线性地址是逻辑地址到物理地址变换之间的中间层。在分段部件中逻辑地址是段中的偏移地址,然后加上基地址就是线性地址。
7.2 Intel逻辑地址到线性地址的变换-段式管理
一个逻辑地址由两部分组成:段标识符和段内偏移量。段标识符是一个16位长的字段组成,称为段选择符,其中前13位是一个索引号。后面三位包含一些硬件细节。
这里面最重要的是Base字段,它描述了一个段的开始位置的线性地址。
Intel设计的本意是,一些全局的段描述符,就放在“全局段描述符表(GDT)”中,一些局部的,例如每个进程自己的,就放在所谓的“局部段描述符表(LDT)”中。
GDT在内存中的地址和大小存放在CPU的gdtr控制寄存器中,而LDT则在ldtr寄存器中。
7.3 Hello的线性地址到物理地址的变换-页式管理
计算机利用页表,通过MMU来完成从虚拟地址到物理地址的转换。
7.4 TLB与四级页表支持下的VA到PA的变换
TLB是一个小的、虚拟寻址的缓存,其中每一行都保存着一个由单一PTE组成的块。TLB通常有高的相联度,从虚拟地址中的页号提取出组选择和行匹配的索引和标记字段。
因为所有的地址翻译都是在芯片上的MMU中进行的,因此非常快。
Core i7是四级页表进行的虚拟地址转物理地址。48位的虚拟地址的前36位被分为四级VPN区。结合存放在CR3的基址寄存器,由前面多级页表的知识,可以确定最终的PPN,与VPO结合得到物理地址。
7.5 三级Cache支持下的物理内存访问
7.6 hello进程fork时的内存映射
7.7 hello进程execve时的内存映射
execve 函数在shell中加载并运行包含在可执行目标文件hello中的程序,用hello程序有效地替代了当前程序。加载并运行hello需要以下几个步骤:
(1)删除已存在的用户区域。删除当前进程(shell)虚拟地址的用户部分中的已存在的区域结构。
(3)映射共享区域。如果hello程序与共享对象(或目标)链接,比如标准C 库libc. so,那么这些对象都是动态链接到这个程序的,然后再映射到用户虚拟地址空间中的共享区域内。
(4)设置程序计数器(PC)。execve做的最后一件事情就是设置当前进程上下文中的程序计数器,使之指向代码区域的入口点。
下一次调度hello进程时,它将从这个入口点开始执行。Linux将根据需要换入代码和数据页面。
7.8 缺页故障与缺页中断处理
接下来,内核从磁盘复制VP3到内存中的PP3,更新PTE3,随后返回。当异常处理程序返回时,它会重新启动导致缺页的指令。
(1)虚拟地址是合法的吗?如果不合法,它就会触发一个段错误。
(2)试图进行的内存访问是否合法?即进程是否有读写或者执行这个区域的权限。
经过上述判断,这时才能确定这是个合法的虚拟地址,然后才会执行上述的替换。
7.9动态存储分配管理
程序中可以进行动态内存分配的内存区域称为堆,堆的管理方法有隐式空闲链表、显式空闲链表、分离的空闲链表等等。
隐式空闲链表即在每个分配块和空闲块的头尾两个单字大小的区域写入块的大小信息和分配信息,这样,块之间就由块大小以及分配信息隐式的连接起来。分配块的时间和堆中所有块数量成正比。
显式空闲链表即在空闲块中存入指向前后空闲块的指针。显式空闲链表的空闲块释放可以采用插入头部策略和根据地址顺序插入链表两种方式。
邻接的空闲块需要合并,为了提高程序效率可以采用分配时合并的方式。
如果堆中已经没有满足申请大小的空闲块,则扩展堆,然后再找符合条件的空闲块。
7.10本章小结
第8章 hello的IO管理
8.1 Linux的IO设备管理方法
8.2 简述Unix IO接口及其函数
设备可以通过Unix I/O接口被映射为文件,这使得所有的输入和输出都能以一种统一且一致的方式来执行:
改变当前的文件位置。 对于每个打开的文件,内核保持着一个文件位置k,初始为0,这个文件位置是从文件开头起始的字节偏移量,应用程序能够通过执行seek,显式地将改变当前文件位置k。
(1)进程是通过调用open函数来打开一个存在的文件或者创建一个新文件的,函数声明如下:
int open(char *filename, int flags, mode_t mode);
(2)进程通过调用close函数关闭一个打开的文件。函数声明如下:
(3)应用程序是通过分别调用read和write函数来执行输入和输出的。函数声明如下:
ssize_t read(int fd, void *buf, size_t n);
ssize_t write(int fd, const void *buf, size_t n);
(4)通过调用lseek函数,应用程序能够显式地修改当前文件的位置。函数声明如下:
off_t lseek(int handle, off_t offset, int fromwhere);
8.3 printf的实现分析
形参列表中的…是可变形参的一种写法,当传递参数的个数不确定时,用这种方式来表示。
va_list的定义如下:typedef char *va_list,说明它是一个字符指针,其中 (char*)(&fmt) + 4) 即arg表示的是...中的第一个参数。
vsprintf程序按照格式fmt结合参数args生成格式化之后的字符串,并返回字串的长度。
在printf中调用系统函数write(buf,i)将长度为i的buf输出。write函数如下:
因此,vsprintf的作用为接受确定输出格式的格式字符串fmt。用格式字符串对个数变化的参数进行格式化,进而产生格式化输出。
int printf(const char *fmt, ...)
va_list arg = (va_list)((char*)(&fmt) + 4);
8.4 getchar的实现分析
异步异常-键盘中断的处理:键盘中断处理子程序。接受按键扫描码转成ascii码,保存到系统的键盘缓冲区。
getchar等调用read系统函数,通过系统调用读取按键ascii码,直到接受到回车键才返回。
getchar调用系统函数read,发送一个中断信号,内核抢占这个进程,用户输入字符串,键入回车后(字符串和回车都保存在缓冲区内),再次发送信号,内核重新调度这个进程,getchar从缓冲区读入字符。
static char* bb=buf;//指向缓冲区的第一个位置的指针
return(--n>=0)?(unsigned char)*bb++:EOF;
8.5本章小结
本章主要介绍了linux的IO设备管理方法和及其接口和函数,并对printf函数和getchar函数的底层实现做了一定的分析。
结论
hello程序从一个高级语言程序hello.c变成可执行的目标文件hello(P2P)、由子进程开始执行到子进程结束被回收(020)的生命周期如下:
将hello.c中include的所有外部的头文件头文件内容直接插入程序文本中。完成字符串的替换,方便后续处理;
通过词法分析和语法分析,将合法指令翻译成等价汇编代码。通过编译过程,编译器将hello.i 翻译成汇编语言文件 hello.s;
将hello.s汇编程序翻译成机器语言指令,并把这些指令打包成可重定位目标程序格式,最终结果保存在hello.o 目标文件中;
通过链接器,将hello的程序编码与动态链接库等收集整理成为一个单一文件,生成完全链接的可执行的目标文件hello;
打开shell,在其中键入 ./hello <学号> <姓名>,终端为其fork新建进程,并通过execve把代码和数据加载入虚拟内存空间,程序开始执行;
在该进程被调度时,CPU为hello其分配时间片,在一个时间片中,hello享有CPU全部资源,PC寄存器一步一步地更新,CPU不断地取指,顺序执行自己的控制逻辑流;
内存管理单元MMU将逻辑地址,一步步映射成物理地址,进而通过三级高速缓存系统访问物理内存/磁盘中的数据;
printf 会调用malloc 向动态内存分配器申请堆中的内存;
进程时刻等待着信号,如果运行途中键入ctr-c ctr-z 则调用shell 的信号处理函数分别进行停止、挂起等操作,对于其他信号也有相应的操作;
shell父进程等待并回收hello子进程,内核删除为hello进程创建的所有数据结构。
附件
文件名 |
功能 |
hello.c |
源程序 |
hello.i |
预处理后得到的文本文件 |
hello.s |
编译后得到的汇编语言文件 |
hello.o |
汇编后得到的可重定位目标文件 |
hello |
链接后得到的可执行目标文件 |
hello.elf |
用readelf读取hello.o得到的ELF格式信息 |
hello_elf.txt |
用readelf读取hello得到的ELF格式信息 |
hello.asm |
反汇编hello.o得到的反汇编文件 |
hello2.asm |
反汇编hello可执行文件得到的反汇编文件 |
参考文献
[1] Randal E. Bryant,David O'Hallaron,《深入理解计算机系统》[M](原书第三版),北京:机械工业出版社,2021:10-1.
哈工大2021~2022春季学期《计算机系统》大作业相关推荐
- 哈工大2022年春季学期计算机系统大作业——程序人生
计算机系统 大作业 题 目 程序人生-Hello's P2P 专 业 人工智能(未来技术) 学 号 7203610716 班 级 20WJ102 学 生 孙铭蔚 ...
- 2022年春季学期计算机系统大作业——程序人生心得体会
计算机系统 大作业 题 目 程序人生-Hello's P2P 专 业 计算学部 学 号 120L021801 班 级 2003006 学 生 郑卓 指 导 ...
- 哈尔滨工业大学2022春季学期CSAPP大作业
此大作业涵盖CSAPP一大本书的内容,可以很好地帮助复习和理解其中的内容. 计算机系统 大作业 题 目 程序人生-Hello's P2P 专 业 计算学部 学 号 120L022308 班 级 200 ...
- 2021春深入理解计算机系统大作业---hello的一生
计算机系统 大作业 题 目 程序人生-Hello's P2P 专 业 计算学部 学 号 120L021725 班 级 2003006 学 生 杨楠 指 导 ...
- 2021春深入理解计算机系统大作业——程序人生
计算机系统 大作业 题 目 程序人生-Hello's P2P 专 业 计算学部 学 号 1190200608 班 级 1903004 学 生 琚晓龙 指 导 ...
- 2022春季学期哈工大计算机系统大作业
计算机系统 计算机系统 大作业 题 目 程序人生-Hello's P2P 专 业 计算学部 学 号 120L022013 班 级 2003007 学 生 王炜栋 ...
- 哈工大 2021春 计算机系统 大作业程序人生
计算机系统 大作业 题 目 程序人生-Hello's P2P 专 业 计算机 学 号 1190200828 班 级 1936601 学 生 赵英帅 指 导 教 师 刘宏伟 计算机科学与技术学院 202 ...
- 2022哈工大计算机系统大作业——程序人生
计算机系统 大作业 题 目 程序人生-Hello's P2P 专 业 人工智能(未来技术) 学 号 120L020301 班 级 2036011 学 生 张思远 ...
- 哈工大计算机系统大作业 程序人生-Hello’s P2P 2022
2022哈工大计算机系统大作业 目录 摘 要 第1章 概述 1.1 Hello简介 1.2 环境与工具 1.3 中间结果 1.4 本章小结 第2章 预处理 2.1 预处理的概念与作用 2.2在Ubun ...
最新文章
- 毫末智行 Fluid 实践:云原生 AI 让汽车变得“更聪明”
- 【2】thinkphp 3.2.3简单介绍
- 学成在线--11.RabbitMQ快速入门
- 世界上没有一模一样的东西_免费是世界上最昂贵的东西
- 艾孜尔江用JS/TS生成随机姓名
- Python用户画像词云图生成并集成到django网站
- 上海宝付知识普及:个人信用到底多重要?
- SpringMVC引入静态org.webjars中资源404
- DevOps八荣八耻了解下,哈哈~
- java学习就去这56个网站论坛(附各种java学习公众号)
- backdrop-filter filter
- php文件是不是死链,怎么判断网站的链接是不是死链接? 百度搜索标准死链官方文档...
- Process finished with exit code 1 解决方法
- BZOJ - 3687
- 2509-Druid监控功能的深入使用与配置-基于SpringBoot-完全使用 .properties配置文件
- dumpsys activity 查看系统运行了哪些任务?
- 自然数学-对数性质证明
- 悬垂指针(Dangling pointer)和野指针(Wild pointer)
- Android hook方式抓包
- 性能测试跑分软件,AE Benchmark(AE性能测试跑分工具) V1.0 免费版