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 下

  1. 先建立两个链接
    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 .
  2. 然后进行编译
    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 并在虚拟机上运行和调试.

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

maven 下载依赖 jhash:2.1.2 和对应 jar 包

原文地址 前言 25年新的一年&#xff0c;那就先更新一篇技术文章吧&#xff0c;这个是这几天刚遇到的一个有意思的bug&#xff0c;记录分享一下 原因分析 在使用maven加载一个项目的时&#xff0c;发现maven的依赖一直无法解析&#xff0c;更换阿里云镜像和中央仓库都没办法…

回归预测 | MATLAB基于RF-Adaboost多输入单输出回归预测

回归预测 | MATLAB基于RF-Adaboost多输入单输出回归预测 目录 回归预测 | MATLAB基于RF-Adaboost多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 回归预测 | MATLAB基于RF-Adaboost多输入单输出回归预测。 1.Matlab实现RF-Adaboost随机森林集成学习…

【网络协议】动态路由协议

前言 本文将概述动态路由协议&#xff0c;定义其概念&#xff0c;并了解其与静态路由的区别。同时将讨论动态路由协议相较于静态路由的优势&#xff0c;学习动态路由协议的不同类别以及无类别&#xff08;classless&#xff09;和有类别&#xff08;classful&#xff09;的特性…

基于SSM实现的垃圾分类平台系统功能实现二

一、前言介绍&#xff1a; 1.1 项目摘要 随着城市化进程的加速和居民生活水平的提高&#xff0c;城市生活垃圾的产量急剧增加&#xff0c;给城市环境管理带来了巨大压力。传统的垃圾处理方式&#xff0c;如填埋和焚烧&#xff0c;不仅占用大量土地资源&#xff0c;还可能对环…

如何实现多级缓存?

本文重点说一说在Java应用中&#xff0c;多级缓存如何实现。 多级缓存是比较常见的一种性能优化的手段&#xff0c;一般来说就是本地缓存分布式缓存。 本地缓存一般采用Caffeine和Guava&#xff0c;这两种是性能比较高的本地缓存的框架。他们都提供了缓存的过期、管理等功能。…

美摄科技为企业打造专属PC端视频编辑私有化部署方案

美摄科技&#xff0c;作为视频编辑技术的先行者&#xff0c;凭借其在多媒体处理领域的深厚积累&#xff0c;为企业量身打造了PC端视频编辑私有化部署解决方案&#xff0c;旨在帮助企业构建高效、安全、定制化的视频创作平台&#xff0c;赋能企业内容创新&#xff0c;提升品牌影…

嵌入式C语言:什么是指针?

目录 一、指针的基本概念 1.1. 定义指针 1.2. 赋值给指针 1.3. 解引用指针 1.4. 指针运算 1.5. 空指针 1.6. 函数参数 1.7. 数组和指针 1.8. 示例代码 二、指针在内存中的表示 2.1. 内存地址存储 2.2. 内存模型 2.3. 指针与硬件交互 2.4. 示例代码 三 、指针的重…

计算机网络相关习题整理

第一讲 传输媒介 【知识点回顾】 两种导线可以减小电磁干扰&#xff1a; 双绞线&#xff08;分为非屏蔽双绞线、屏蔽双绞线&#xff09;&#xff08;RJ-45用&#xff09;同轴电缆&#xff08;短距离使用&#xff09;网络通信的基本单位&#xff1a;位&#xff08;bit&#xff…

应急响应之入侵排查(下)

一.进程排查 1.Windows 任务管理器查看 在 Windows 系统中&#xff0c;可通过任务管理器查看进程信息。操作步骤为&#xff1a;在任务管理器界面&#xff0c;于 “查看” 选项中选择 “选择列”&#xff0c;随后添加 “映像路径名称” 和 “命令行”&#xff0c;以此查看更多进…

极狐GitLab 正式发布安全版本17.7.1、17.6.3、17.5.5

本分分享极狐GitLab 补丁版本 17.7.1, 17.6.3, 17.5.5 的详细内容。这几个版本包含重要的缺陷和安全修复代码&#xff0c;我们强烈建议所有私有化部署用户应该立即升级到上述的某一个版本。对于极狐GitLab SaaS&#xff0c;技术团队已经进行了升级&#xff0c;无需用户采取任何…

力扣经典二分题:4. 寻找两个正序数组的中位数

题目链接&#xff1a;4. 寻找两个正序数组的中位数 - 力扣&#xff08;LeetCode&#xff09; 一、题目分析 这道题目是让我们在 两个正序的数组中寻找中位数已知两个数组的大小分别是&#xff1a;int m nums1.size(),n nums2.size();中位数性质1&#xff1a;中位数左侧元素 …

安装yarn时显示npm使用淘宝镜像安装报错

问题描述&#xff1a; npm使用淘宝镜像安装报错 错误原因&#xff1a; 淘宝原镜像域名&#xff08;registry.npm.taobao.org&#xff09;的 HTTPS 证书正式到期&#xff0c;npm 淘宝镜像已经从 registry.npm.taobao.org 切换到了 registry.npmmirror.com。解决方案&#xff1a;…

【Python】Python之Selenium基础教程+实战demo:提升你的测试+测试数据构造的效率!

这里写目录标题 什么是Selenium&#xff1f;Selenium基础用法详解环境搭建编写第一个Selenium脚本解析脚本脚本执行结果常用的元素定位方法常用的WebDriver方法等待机制 Selenium高级技巧详解页面元素操作处理弹窗和警告框截图和日志记录多窗口和多标签页操作 一个实战的小demo…

Seata搭建

1.初识Seata Quick Start | Apache Seata 官网 2.准备nacos和 seata 启动nacos startup.cmd -m standalone账号nacos 密码nacos 搭建seata TC 这里下载的 1.4.2 seata-server-1.4.2 1.修改seata配置文件 registry.conf 这里我们使用nacos作为注册中心 和 配置中心 r…

selenium+pyqt5自动化工具总结

说明&#xff1a;本工具是&#xff0c;操作外部google浏览器、selenium是无法操作qt界面中嵌套的浏览器的&#xff0c; 工具在后面 1. 代码结构 pycharm打开的文件下&#xff0c;再写一个子文件&#xff0c;文件导入的时候把子文件名带上 这样就可以在 外层使用命令 pyinst…

.NET 终止或结束进程

如何使用 C# 终止进程。 使用简单的方法终止.NET中的现有进程Process.Kill()。有一个可选参数 true 或 false&#xff0c;用于结束与要结束的进程相关的所有子进程。 了解如何创建流程。 结束当前进程&#xff1a; System.Diagnostics.Process.GetCurrentProcess().Kill(tru…

怎么实现Redis的高可用?

大家好&#xff0c;我是锋哥。今天分享关于【怎么实现Redis的高可用&#xff1f;】面试题。希望对大家有帮助&#xff1b; 怎么实现Redis的高可用&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 为了实现 Redis 的高可用性&#xff0c;我们需要保证在发…

大数据技术实训:Hadoop完全分布式运行模式配置

准备&#xff1a; 1&#xff09;准备3台客户机&#xff08;关闭防火墙、静态ip、主机名称&#xff09; 2&#xff09;安装JDK 3&#xff09;配置环境变量 4&#xff09;安装Hadoop 5&#xff09;配置环境变量 6&#xff09;配置集群 7&#xff09;单点启动 8&#xff09;配置ss…

【Uniapp-Vue3】Prop校验与prop默认值用法及循环遍历数组对象

一、prop校验 如果我们在想要限制prop的类型&#xff0c;就可以在接收prop的时候对接收类型进行限制&#xff1a; defineProps({ 属性名:{ type:类型 } }) 需要注意类型的首字母大写 但是设置了传入参数类型限制并不能严格限制&#xff0c;只会在后台进行提示&#xff1a; 二、…

开启Excel导航仪,跨表跳转不迷路-Excel易用宝

都2025年了&#xff0c;汽车都有导航了&#xff0c;你的表格还没有导航仪吗&#xff1f;那也太OUT了。 面对着一个工作簿中有N多个工作表&#xff0c;工作表中又有超级表&#xff0c;数据透视表&#xff0c;图表等元素&#xff0c;如何快速的切换跳转到需要查看的数据呢&#…