ubuntu20下编译linux1.0 (part1)
author: hjjdebug
date: 2025年 01月 09日 星期四 15:56:15 CST
description: ubuntu20下编译linux1.0 (part1)
该博客记录了新gcc编译旧代码可能碰到的问题和解决办法, 可留作参考
操作环境: ubuntu20
$ gcc --version
gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0
$ as --version
GNU 汇编器 (GNU Binutils for Ubuntu) 2.34
$ ld --version
GNU ld (GNU Binutils for Ubuntu) 2.34
文章目录
- 1. 下载源码:
- 2. 根据readme, 将代码解压到/usr/src/linux 下
- 3 解决 dep 依赖问题
- 4 生成内核文件,解决一系列编译连接问题
- 5 最后的问题: tools/zSystem 已经生成后, 内核压缩问题
- 6 小结:
操作过程:
1. 下载源码:
https://www.kernel.org/pub/linux/kernel/v1.0/linux-1.0.tar.gz
2. 根据readme, 将代码解压到/usr/src/linux 下
- 先建立两个链接
cd /usr/include
mv linux linux_orig
mv asm asm_orig
ln -s /usr/src/linux/include/linux .
ln -s /usr/src/linux/include/asm . - 然后进行编译
make config //一路回车全给默认
make dep
make
说起来就3步make, 但是第二步make dep 就不那么顺利了.
3 解决 dep 依赖问题
$ make dep
make[2]: 进入目录“/usr/src/linux/drivers/char”
gcc -D__KERNEL__ -E -M tty_io.c console.c keyboard.c serial.c tty_ioctl.c pty.c vt.c mem.c defkeymap.c psaux.c mouse.c > .depend
serial.c:538:8: error: macro names must be identifiers
538 | #ifdef 0
| ^
make[2]: *** [Makefile:78:dep] 错误 1
make[2]: 离开目录“/usr/src/linux/drivers/char”
make[1]: *** [Makefile:39:dep] 错误 2
make[1]: 离开目录“/usr/src/linux/drivers”
make: *** [Makefile:253:dep] 错误 2
错误位置: drivers/char/serial.c 文件第538行有#ifdef 0, 使的dep构建不能通过
错误原因: #ifdef 0 在新gcc 中已经不合法
解决办法: 改为 #if 0
顺便把./fs/buffer.c:#ifdef 0 也改掉
In file included from /usr/include/x86_64-linux-gnu/asm/socket.h:1,
from /usr/include/x86_64-linux-gnu/bits/socket.h:354,
from /usr/include/x86_64-linux-gnu/sys/socket.h:33,
from /usr/include/netinet/in.h:23,
from plip.c:87:
/usr/include/asm-generic/socket.h:5:10: fatal error: linux/posix_types.h: 没有那个文件或目录
5 | #include <linux/posix_types.h>
| ^~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make[3]: *** [Makefile:143:dep] 错误 1
make[3]: 离开目录“/usr/src/linux/drivers/net”
make[2]: *** [Makefile:39:dep] 错误 2
make[2]: 离开目录“/usr/src/linux/drivers”
make[1]: *** [Makefile:253:depend] 错误 2
make[1]: 离开目录“/usr/src/linux”
make: *** [Makefile:262:…depend] 错误 2
错误位置: drivers/net/plip.c:87调用/usr/include/netinet/in.h, 最后缺失文件linux/posix_types.h
错误原因: 它打开了新版本的netinet/in.h 文件,再访问旧版本linux目录,因而找不到指定文件
解决办法: 把新版本的posix_types.h 拷贝进linux 目录, 令依赖通过
cp /usr/include/linux_orig/posix_types.h /usr/include/linux
解决了上面2个错误, make dep 就通过了,下面开始make
4 生成内核文件,解决一系列编译连接问题
$ make
gcc -D__KERNEL__ -E -traditional boot/head.S -o boot/head.s
as -c -o boot/head.o boot/head.s
boot/head.S: Assembler messages:
boot/head.S:64: 错误: invalid instruction suffix for push' boot/head.S:65: 错误: invalid instruction suffix for popf’
boot/head.S:99: 错误: invalid instruction suffix for `pushf’
…
错误位置: boot/head.S 中有一堆编译错误.
错误原因:现在的as 默认是64位的,需要改成32位编译
解决办法:打开Makefile , 将 AS = as 改为 AS = as --32
gcc -D__KERNEL__ -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -m486 -c -o init/main.o init/main.c
gcc: error: unrecognized command line option ‘-m486’
错误原因:新gcc已经没有该选项了, 但应该加-m32标志,表示编译的是32位程序,否则默认是64位程序
解决办法:打开Makefile , 注释掉-m486标志, 但应该添加-m32标志, 表示编译的程序是32位的.
#CFLAGS := $(CFLAGS) -m486
HOSTCC =gcc -m32
CC =gcc -D__KERNEL__ -m32
In file included from init/main.c:10:
/usr/include/asm/io.h: In function ‘__inbc’:
/usr/include/asm/io.h:78:1: error: impossible constraint in ‘asm’
78 | __IN(b,“b”,“0” (0))
| ^~~~
make: *** [Makefile:149:init/main.o] 错误 1
错误位置: 在init/main.c第10行,包含asm/io.h, 此文件的第78行,在宏展开过程中,有不正确的asm写法
错误原因: 这个问题比较复杂, 是因为新版gcc 中, 已经不使用extern inline, 代之以inline
解决办法: 把 extern inline 中的extern 去掉. (先处理一下这个io.h文件,看看效果)
该错误解决后,又出现如下错误.
In file included from /usr/include/linux/sched.h:77,
from init/main.c:15:
/usr/include/linux/mm.h: In function ‘get_free_page’:
/usr/include/linux/mm.h:98:3: error: ‘asm’ operand has impossible constraints
98 | asm volatile(“rep ; stosl”
| ^~~~~~~
make: *** [Makefile:149:init/main.o] 错误 1
错误位置: 在init/main.c第15行,包含linux/sched.h, 此文件的第77行,包含linux/mm.h
在其第98行, get_free_page 函数中, 有不正确的asm写法
错误原因: 新版gcc 内嵌汇编 已经不再需要在第3部分添加变化寄存器说明.
解决办法:去掉变换寄存器部分
原代码:
asm volatile(“rep ; stosl”
: /* no outputs /
:“a” (0),“c” (1024),“D” (page)
:“di”,“cx”);
修改后代码:
asm volatile(“rep ; stosl”
: / no outputs */
:“a” (0),“c” (1024),“D” (page)
😃;
编译通过,继续.
In file included from init/main.c:19:
/usr/include/linux/string.h: In function ‘strcpy’:
/usr/include/linux/string.h:24:1: error: ‘asm’ operand has impossible constraints
24 | asm(“cld\n”
| ^~~~~~~
make: *** [Makefile:149:init/main.o] 错误 1
错误位置: init/main.c:19 ->linux/string.h:24, strcpy函数中,
错误原因: asm 书写不合法, 有不可能约束.
解决办法: 要去掉变换寄存器约束, 跟上一条处理方法一样.
内嵌汇编由于新版的gcc 已经改为不需要第3部分变换寄存器说明,所以这一改动会大量修改内核代码
你可以通过在.h, .c 中查找"ax" 寄存器或者"cx"寄存器来找到它们并修改
./include/linux/mm.h
./include/linux/sched.h
./include/linux/string.h
./include/linux/delay.h
./include/asm/segment.h
./include/asm/system.h
以下.c文件可能需要修改
$ find . -name “*.c”|xargs grep -l -w ax
./mm/memory.c
./kernel/traps.c
./fs/minix/bitmap.c
./fs/proc/base.c
./fs/isofs/namei.c
./fs/ext2/balloc.c
./fs/ext2/ialloc.c
./fs/ext/namei.c
./net/inet/loopback.c
./net/inet/ip.c
./net/inet/tcp.c
./net/inet/udp.c
./init/main.c
./drivers/FPU-emu/fpu_trig.c
./drivers/net/3c501.c
./drivers/sound/audio.c
./drivers/char/console.c
打开文件查看,需要改就改! 改不完全也没关系,让编译器去检查.
纯手工活,批量改也是手工活,没有统一规律,谁对编辑器熟悉改的就快一点,例如emacs
这样就解决了内嵌汇编语法问题.
sched.c:41:25: error: conflicting type qualifiers for ‘xtime’
41 | volatile struct timeval xtime; /* The current time */
| ^~~~~
In file included from sched.c:16:
/usr/include/linux/sched.h:308:23: note: previous declaration of ‘xtime’ was here
308 | extern struct timeval xtime;
| ^~~~~
错误位置: sched.c:41 行 声明了 volatile struct timeval xtime,与sched.c:16行包含了
linux/sched.h:308行中的声明 extern struct timeval xtime 相冲突
错误原因: 两处变量声明类型不一致,新版gcc 检查更严格
解决办法:加上volatile 关键字使完全一致,
extern volatile struct timeval xtime;
另外, 把time.c 中的 extern struct timeval xtime 也改为 extern volatile struct timeval xtime
这样编译就通过了,进入下一步链接问题.
ld -r -o kernel.o sched.o sys_call.o traps.o irq.o dma.o fork.o panic.o printk.o vsprintf.o sys.o module.o ksyms.o exit.o signal.o mktime.o ptrace.o ioport.o itimer.o info.o ldt.o time.o
ld: traps.o: in function tas': traps.c:(.text+0x0): multiple definition of tas’; sched.o:sched.c:(.text+0x830): first defined here
ld: traps.o: in function verify_area': traps.c:(.text+0x20): multiple definition of verify_area’; sched.o:sched.c:(.text+0x850): first defined here
ld: traps.o: in function `get_free_page’:
ld -r -o kernel.o sched.o sys_call.o traps.o …
错误位置: 连接错误, 在traps.c 中有tas 定义, 但是sched.c 中也有tas 定义
同理,在traps.c 中有verify_area函数定义,在sched.c 中也有verify_area函数定义
同理,在traps.c 中有get_free_page函数定义,在sched.c 中也有get_free_page函数定义
首先先解决一个基本问题
ld 生成32bit 还是64bit 的选择问题
ld 应该加上选项 -m elf_i386 ,使生成 32bit 的库
打开Makefile ,
将
LD =ld
改为
LD =ld -m elf_i386
然后来解决多重定义问题:
错误原因: get_free_page 是在mm.h中定义的 extern inline unsigned long 函数,并在头文件中定义了函数体.
调用它的地方在多个文件中包含该头文件, 显然它并没有在调用的地方inline 而是似乎定义了多个函数体
新版的gcc 要想inline, 只需要声明inline, 不再需要声明为extern inline
解决办法: 将extern inline … 改为 inline … 这一改动又引起了许多文件的改动!!
$ find . -name “.c" -o -name ".h” |xargs grep -l “extern inline”
./include/linux/sysv_fs.h
./include/linux/mm.h
./include/linux/sched.h
./include/linux/locks.h
./include/linux/interrupt.h
./include/linux/string.h
./include/asm/system.h
./fs/sysv/balloc.c
./drivers/net/atp.h
./drivers/sound/audio.c
./drivers/char/kbd_kern.h
不过这次改动比较简单,因为是固定改动,一个查找替换就可以了.
需要make clean , 消除原来生成的.o文件
再make, 重新生成.o文件
但是问题还没有完全解决, 还有一些连接问题
ld -m elf_i386 -r -o kernel.o sched.o sys_call.o traps.o irq.o dma.o fork.o panic.o printk.o vsprintf.o sys.o module.o ksyms.o exit.o signal.o mktime.o ptrace.o ioport.o itimer.o info.o ldt.o time.o
ld: vsprintf.o: in function strcpy': vsprintf.c:(.text+0x320): multiple definition of strcpy’; traps.o:traps.c:(.text+0x0): first defined here
ld: vsprintf.o: in function strncpy': vsprintf.c:(.text+0x340): multiple definition of strncpy’; traps.o:traps.c:(.text+0x20): first defined here
就是 string.h 文件还是有多重定义,为何?
错误原因: 象strcpy, strcmp 等这些常用的string.h 中的函数, 现代gcc 默认都使用它内置的形式,而不采用用户定义的形式.
解决方法: 在CFLAGS 上加上 -fno-builtin 这样就会使用用户的代码从而消除了重复定义. 这是我参考了0.11源码编译发现的.
打开Makefile
将
CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe
改为
CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-builtin
需要make clean , 消除原来生成的.o文件
再make, 重新生成.o文件
fpu_entry.c:473:24: error: lvalue required as left operand of assignment
473 | FPU_data_address = 0;
错误原因: 左值需要左操作数赋值 , 左值FPU_data_address 定义的是(void *)
解决办法: 去掉(void *)
#define FPU_data_address ((void *)(I387.soft.twd)) 改为
#define FPU_data_address (I387.soft.twd)
继续make, 还有许多警告 -Wstrict-aliasing
fpu_emu.h:136:5: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
现在没空管这些警告, 尤其是这种严格的警告需要关闭,
解决办法: 打开Makefile
将
CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-builtin
改为
CFLAGS = -Wall -O2 -fomit-frame-pointer -pipe -fno-builtin
这样输出就会好很多!
还是没有关掉-Wstrict-aliasing, 算了,那是-Wall 引起的,就这样吧,先不理它了.
fpu_trig.c:748:17: error: missing terminating " character
748 | asm volatile ("movl %2,%%eax; mull %4; subl %%eax,%0; sbbl %%edx,%1;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fpu_trig.c:749:18: error: expected string literal before ‘movl’
749 | movl %3,%%eax; mull %4; subl %%eax,%1;
错误原因: 内嵌汇编不能只用一对双引号把块扩起来,而应该每行都加双引号
解决办法: 每行加双引号.
这种改动因为没有统一性,又是一种纯手工活,碰到了改就是了.
exec.c: In function ‘copy_strings’:
exec.c:380:44: error: lvalue required as left operand of assignment
380 | !(pag = (char *) page[p/PAGE_SIZE] =
| ^
将:
if (!(pag = (char *) page[p/PAGE_SIZE]) &&
!(pag = (char *) page[p/PAGE_SIZE] =
(unsigned long *) get_free_page(GFP_USER)))
return 0;
改为:
if (!(pag = (char *) page[p/PAGE_SIZE]))
{
pag = get_free_page(GFP_USER);
page[p/PAGE_SIZE] = pag;
if(!pag) return 0;
}
ld -m elf_i386 -r -o minix.o bitmap.o truncate.o namei.o inode.o file.o dir.o symlink.o fsync.o
ld: inode.o: in function set_bit': inode.c:(.text+0x860): multiple definition of set_bit’; bitmap.o:bitmap.c:(.text+0x130): first defined here
查看inode.c 的set_bit, 发现其定义为
extern inline int set_bit(int nr,int * addr)
把 extern 去掉 即可.
同时发现 dma.h 中也需要如此修改
继续,还有汇编问题
balloc.c:106: 错误: junk $0' after expression balloc.c:106: 错误: junk repnz’ after register
将
asm(
" cld"
" mov $0,%%eax"
…
改为
asm(
" cld\n\t"
" mov $0,%%eax\n\t"
即每行应加上\n, 又是手工活, 不过在emacs或vim中编辑可以用宏命令简化
sock.c:331:17: error: lvalue required as left operand of assignment
331 | UN_DATA(sock) = upd;
解决办法:
//UN_DATA(sock) = upd;
sock->data = upd;
gcc -D__KERNEL__ -m32 -Wall -O2 -fomit-frame-pointer -pipe -fno-builtin -c -o arp.o arp.c
arp.c:126:27: error: conflicting type qualifiers for ‘arp_q’
126 | struct sk_buff * volatile arp_q = NULL;
| ^~~~~
In file included from arp.c:80:
arp.h:48:24: note: previous declaration of ‘arp_q’ was here
48 | extern struct sk_buff *arp_q;
解决办法, 前面有说明,加volatile 成完全一致
至此,编译已经通过,解决最后的连接问题.
ld -m elf_i386 -Ttext 100000 boot/head.o init/main.o tools/version.o
kernel/kernel.o mm/mm.o fs/fs.o net/net.o ipc/ipc.o
fs/filesystems.a
drivers/block/block.a drivers/char/char.a drivers/net/net.a ibcs/ibcs.o drivers/FPU-emu/math.a
lib/lib.a
-o tools/zSystem
ld: 警告: 无法找到项目符号 _start; 缺省为 0000000000100000
ld: kernel/kernel.o: in function sys_alarm': (.text+0x266): undefined reference to __stack_chk_fail_local’
错误原因: __stack_chk_fail_local 是新gcc 为安全启用的一个选项,系统文件中不包含该符号.
我们检查很多.o文件都包含__stack_chk_fail_local 符号.
解决办法: CFLAGS 中加上-fno-stack-protector
将
CFLAGS = -Wall -O2 -fomit-frame-pointer -pipe -fno-builtin
改为:
CFLAGS = -Wall -O2 -fomit-frame-pointer -pipe -fno-builtin -fno-stack-protector
重新make clean; make
继续:
ld: kernel/kernel.o: in function schedule': (.text+0xa2f): undefined reference to _current’
ld: (.text+0xa38): undefined reference to _current' ld: (.text+0xa45): undefined reference to _last_task_used_math’
ld: kernel/kernel.o: in function `__down’:
current 明明在schedule.c 中定义了,却为和说未定义?
错误原因: 现在gcc的c语言 符号名不再自动加下划线了.
解决办法: 需要把对_current 的引用改为current,
ld: kernel/kernel.o: in function sched_init': (.text+0x12e2): undefined reference to gdt’
ld: (.text+0x133c): undefined reference to idt' ld: (.text+0x1342): undefined reference to system_call’
错误原因: 还是上面原因,新gcc不再把.c文件的符号自动加下划线, 所以.S 与 .C 中文件符号要重新对应
解决办法: 需要把head.S 中的 _gdb 改成gdt, _idt 改成 idt 等等.
起作用的是 .globl _idt,_gdt,
总之,解决这个需要在.S,中定义导出的下划线去掉, 调用的下划线也去掉. 又是一个手工活,怎么顺手怎么来吧。
ld: kernel/kernel.o:(.data.rel.ro+0x0): undefined reference to bad_IRQ0_interrupt' ld: kernel/kernel.o:(.data.rel.ro+0x4): undefined reference to bad_IRQ1_interrupt’
irq.h 中有一个宏,BUILD_IRQ, 其中有asm 内链汇编, 把标号名称去掉下划扛.
即将
“_bad_IRQ” #nr "interrupt:\n\t"
SAVE_MOST
ACK##chip(mask)
RESTORE_MOST
改为:
“bad_IRQ” #nr "interrupt:\n\t"
SAVE_MOST
ACK##chip(mask)
RESTORE_MOST
同样: _IRQ, _fast_IRQ 也要去掉下划线
ld: kernel/kernel.o: in function sys_get_kernel_syms': (.text+0x65cc): undefined reference to symbol_table_size’
ld: (.text+0x6621): undefined reference to `symbol_table’
这要改ksyms.sh 文件, 去掉下划线,这样生成的 .s 文件不再有下划线.
关于.S, .c 符号一致性问题也就这么多了, 好好用find, grep 来定位问题,结合emacs,vim编辑
make[1]: 进入目录“/usr/src/linux/zBoot”
gcc -D__KERNEL__ -m32 -O2 -DSTDC_HEADERS xtract.c -o xtract
xtract.c:18:10: fatal error: a.out.h: 没有那个文件或目录
18 | #include <a.out.h>
解决办法:
18 | #include <a.out.h>
改为
#include <linux/a.out.h>
实际上xtract 工具已经不使用它了, 因为它操作的是OMAGIC格式文件,而现在生成的是elf32
ld -m elf_i386 -o zSystem -Ttext 1000 head.o inflate.o unzip.o misc.o piggy.o
piggy.o: file not recognized: file format not recognized
make[1]: *** [Makefile:21:zSystem] 错误 1
make[1]: 离开目录“/usr/src/linux/zBoot”
5 最后的问题: tools/zSystem 已经生成后, 内核压缩问题
此时 tools/zSystem 已经生成!!
make -C zBoot
make[1]: 进入目录“/usr/src/linux/zBoot”
./xtract …/tools/zSystem | gzip -9 | ./piggyback > piggy.o
Non-GCC header of ‘system’
Compressed size 20.
ld -m elf_i386 -o zSystem -Ttext 1000 head.o inflate.o unzip.o misc.o piggy.o
piggy.o: file not recognized: file format not recognized
make[1]: *** [Makefile:21:zSystem] 错误 1
我们可以研究一下zBoot 如何组装数据,有2个执行程序, xtract, piggyback
2个小程序, 代码很少,可以阅读.
xtract 它抽取的是OMAGIC 格式的文件,但现在ld生成的是elf格式,该函数可以用脚本替换.
piggyback, 用来生成piggy.o 的文件 但它是OMAGIC 格式的.
tools/zSystem 是一个非压缩内核,它已经生成.
但没有生成压缩的内核,因为新版本ld 已经不支持OMAGIC格式的文件了,
piggy.o 是把未压缩内核变成OMAGIC类型纯数据文件,但ld已经不支持了. ubuntu18下还是支持的.
ubuntu18 下的ld 是 ld --version 2.30
ubuntu20 下:
ld --version
GNU ld (GNU Binutils for Ubuntu) 2.34
只能放弃OMAGIC 格式, xtract,piggyback 都不能使用了, 需要用elf32 格式的文件
有时间再继续!
6 小结:
由于汇编as,连接ld,及编译gcc的更新,代码及编译环境需要进行相应的调整
解决了一系列编译连接问题, 生成了未压缩的内核文件.
最后由于ld不能支持OMAGIC 格式文件,压缩的内核未能生成.
另,如果改用非压缩内核也会有问题,因为非压缩内核默认配置下编译出大大小是700多K,超过setup所能容纳
的容量,约512K, setup.s 程序不方便改,因为它把内核放到0地址,而0xA0000或0xB8000地址是显示区,所以
内核大小受到了限制.
所以这一篇就先到编译出内核为止,生成tools/zSystem
下一篇继续解决压缩内核问题.
后面的任务包括编译出可启动影像zImage 并在虚拟机上运行和调试.
相关文章:
ubuntu20下编译linux1.0 (part1)
author: hjjdebug date: 2025年 01月 09日 星期四 15:56:15 CST description: ubuntu20下编译linux1.0 (part1) 该博客记录了新gcc编译旧代码可能碰到的问题和解决办法, 可留作参考 操作环境: ubuntu20 $ gcc --version gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0 $ as --vers…...
欧拉公式和傅里叶变换
注:英文引文机翻,未校。 中文引文未整理去重,如有异常,请看原文。 Euler’s Formula and Fourier Transform Posted byczxttkl October 7, 2018 Euler’s formula states that e i x cos x i sin x e^{ix} \cos{x} i …...
Jenkins内修改allure报告名称
背景: 最近使用Jenkins搭建自动化测试环境时,使用Jenkins的allure插件生成的报告,一直显示默认ALLURE REPORT,想自定义成与项目关联的名称,如图所示,很明显自定义名称显得高大上些,之前…...
30天开发操作系统 第 12 天 -- 定时器 v1.0
前言 定时器(Timer)对于操作系统非常重要。它在原理上却很简单,只是每隔一段时间(比如0.01秒)就发送一个中断信号给CPU。幸亏有了定时器,CPU才不用辛苦地去计量时间。……如果没有定时器会怎么样呢?让我们想象一下吧。 假如CPU看不到定时器而仍想计量时…...
Ubuntu | PostgreSQL | 解决 ERROR: `xmllint` is missing on your system.
解决 sudo apt install apt-file sudo apt-file updatesudo apt-file search xmllint sudo apt install libxml2-utils执行 # postgres源码安装包解压文件夹中 make install make install问题 make -C src install make[2]: Entering directory /home/postgres/postgresql-1…...
uniapp使用chooseLocation安卓篇
本文章全部以高德地图为例 代码 <view class"bottom"><button click"choose">定位</button> </view> choose() {uni.chooseLocation({success: function(res) {console.log(位置名称: res.name);console.log(详细地…...
《PC 上的开源神经网络多模态模型:开启智能交互新时代》
《PC 上的开源神经网络多模态模型:开启智能交互新时代》 一、引言二、多模态模型基础剖析(一)核心概念解读(二)技术架构探秘 三、开源多模态模型的独特魅力(一)开源优势尽显(二&…...
Apache JMeter 压力测试使用说明
文章目录 一、 安装步骤步骤一 下载相关的包步骤二 安装 Jmeter步骤三 设置 Jmeter 工具语言类型为中文 二、使用工具2.1 创建测试任务步骤一 创建线程组步骤二 创建 HTTP 请求 2.2 配置 HTTP 默认参数添加 HTTP消息头管理器HTTP请求默认值 2.3 添加 查看结果监听器2.4 查看结果…...
腾讯云AI代码助手编程挑战赛-知识百科AI
作品简介 知识百科AI这一编程主要用于对于小朋友的探索力的开发,让小朋友在一开始就对学习具有探索精神。在信息化时代下,会主动去学习自己认知以外的知识,同时丰富了眼界,开拓了新的知识。同时催生了在大数据时代下的信息共享化…...
【SpringAOP】Spring AOP 底层逻辑:切点表达式与原理简明阐述
前言 🌟🌟本期讲解关于spring aop的切面表达式和自身实现原理介绍~~~ 🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客 🔥 你的点赞就是小编不断更新的最大动力 &am…...
HTTP-响应协议
HTTP的响应过程? 浏览器请求数据--》web服务器过程:请求过程 web服务器将响应数据-》到浏览器:响应过程 响应数据有哪些内容? 1.和请求数据类似。 2. 响应体中存储着web服务器返回给浏览器的响应数据。并且注意响应头和响应体之间…...
SQL进阶实战技巧:即时订单比例问题
目录 0 需求描述 1 数据准备 2 问题分析 3 小结 往期精彩 0 需求描述 订单配送中,如果期望配送日期和下单日期相同,称为即时订单,如果期望配送日期和下单日期不同,称为计划订单。 请从配送信息表(delivery_info)中求出每个用户的首单(用户的第一个订单)中即时订单…...
什么是端口
端口是用来区分同一网络设备(IP地址)上运行的不同服务或应用程序接收外部数据的窗口。 以下是几个要点: 对于我们发送请求指定的url中的端口,指的是对方服务器的用于接收数据的端口,如http的80端口,服务器通常都会设定要监听来自…...
【Flutter】使用ScrollController配合EasyRefresh实现列表预加载:在还未滑动到底部时加载下一页数据
需求/背景 在我们的业务场景中,列表的加载使用easy_refresh组件: https://pub.dev/packages/easy_refresh 大概效果是往上滑动到一定的offset会触发一个上滑加载,可以触发一些网络请求拉取列表后面的数据来展示。 这种模式一般在一页翻完…...
【2025 Rust学习 --- 11 实用工具特型01】
清理特型Drop 当一个值的拥有者消失时,Rust 会丢弃(drop)该值。丢弃一个值就必须释放 该值拥有的任何其他值、堆存储和系统资源。 丢弃可能发生在多种情况下: 当变量超出作用域时;在表达式语句的末尾;当…...
网络安全基础以及概念
1. 安全领域的概念 1.1 网络产品 1. EDR:终端检测与响应(Endpoint Detection and Response),终端主要包括我们的笔记本、台式机、手机、服务器等,EDR是一种运行在终端上安全软件,主要负责监控网络流量、可疑进程、注册表活动等其他安全相关的事件与活动。当发现有威胁是自…...
windows和linux的抓包方式
1.实验准备: 一台windows主机,一台linux主机 wireshark使用: 打开wireshark,这些有波动的就代表可以有流量经过该网卡,选择一张有流量经过的网卡 可以看到很多的流量,然后可以使用过滤器来过滤想要的流量…...
【Uniapp-Vue3】v-if条件渲染及v-show的选择对比
如果我们想让元素根据响应式变量的值进行显示或隐藏可以使用v-if或v-show 一、v-show 另一种控制显示的方法就是使用v-show,使用方法和v-if一样,为true显示,为false则不显示。 二、v-if v-if除了可以像v-show一样单独使用外,还…...
宝塔面板使用 GoAccess Web 日志分析教程
宝塔面板是一个简单方便的服务器运维面板,但其网站统计功能是收费的。而 GoAccess 是一个用 C 编写的免费开源 Web日志分析器,本文将介绍如何在宝塔面板中开启 GoAccess Web 日志分析功能。 内容索引 下载安装 GoAccess在宝塔面板中添加日志切割的计划任务将 Web 日志输出到…...
Windows 安装 Docker 和 Docker Compose
🚀 作者主页: 有来技术 🔥 开源项目: youlai-mall ︱vue3-element-admin︱youlai-boot︱vue-uniapp-template 🌺 仓库主页: GitCode︱ Gitee ︱ Github 💖 欢迎点赞 👍 收藏 ⭐评论 …...
Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
阿里云Ubuntu 22.04 64位搭建Flask流程(亲测)
cd /home 进入home盘 安装虚拟环境: 1、安装virtualenv pip install virtualenv 2.创建新的虚拟环境: virtualenv myenv 3、激活虚拟环境(激活环境可以在当前环境下安装包) source myenv/bin/activate 此时,终端…...
在 Visual Studio Code 中使用驭码 CodeRider 提升开发效率:以冒泡排序为例
目录 前言1 插件安装与配置1.1 安装驭码 CodeRider1.2 初始配置建议 2 示例代码:冒泡排序3 驭码 CodeRider 功能详解3.1 功能概览3.2 代码解释功能3.3 自动注释生成3.4 逻辑修改功能3.5 单元测试自动生成3.6 代码优化建议 4 驭码的实际应用建议5 常见问题与解决建议…...
数据库——redis
一、Redis 介绍 1. 概述 Redis(Remote Dictionary Server)是一个开源的、高性能的内存键值数据库系统,具有以下核心特点: 内存存储架构:数据主要存储在内存中,提供微秒级的读写响应 多数据结构支持&…...
