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…...
【AI日记】25.01.10
【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】【读书与思考】 AI kaggle 比赛:Forecasting Sticker Sales 读书 书名:国家为什么会失败阅读原因:2024 年诺贝尔经济学奖得主的力作未删减版:https://book.dou…...
04_Redis数据类型-String字符串
1.Redis数据类型介绍 Redis是一种Key-Value类型缓存型数据库,Redis为了存储不同类型的数据,Value支持多种数据类型,Redis为我们提供了常用的9种数据类型。包括5种基本类型:String(字符串)、Hash(哈希)、List(列表),Set(集合)及zset(Sorted Set有序集合);和4种…...
mysql之基本select语句 运算符 排序分页
1.SQL的分类 DDL:数据定义语言. CREATE ALTER DROP RENAME TRUNCATE DML: 数据操作语言. INSERT DELETE UPDATE SELECT 重中之重 DCL: 数据控制语言. COMMIT ROLLBACK SAVEPOINT GRANT REVOKE 2.SQL语言的规则与规范 1.基本规则 SQL可以在一行或多行,为了提高可…...
springboot整合admin
1. 添加依赖 首先,在你的admin服务端pom.xml文件中添加Spring Boot Admin的依赖: <dependency><groupId>de.codecentric</groupId><artifactId>spring-boot-admin-starter-server</artifactId><version>2.5.4<…...
springboot整合gateway
1. 添加依赖 首先,在你的pom.xml文件中添加Spring Cloud Gateway的依赖: <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId> </dependency> 如果…...
iOS实际开发中使用Alamofire实现多文件上传(以个人相册为例)
引言 在移动应用中,图片上传是一个常见的功能,尤其是在个人中心或社交平台场景中,用户经常需要上传图片到服务器,用以展示个人风采或记录美好瞬间。然而,实现多图片上传的过程中,如何设计高效的上传逻辑并…...
PyCharm 的安装与使用(Window)
1 PyCharm 简介 PyCharm 是一款由 JetBrains 公司开发的专门用于 Python 语言开发的集成开发环境(IDE)。以下是其相关介绍: 1.1 特点与功能 智能代码编辑:提供高度智能化的代码编辑器,支持语法高亮、自动补全、代码重…...
媒体资源生产转码过程
音视频基础 1. 音频基础原理 1.1 声音的基本概念 声波: 声音是通过空气或其他介质传播的机械波。声波的特性包括频率(Hz)、振幅(dB)和波形。采样率 (Sampling Rate): 每秒对声音信号进行采样的次数,单位为赫兹&…...
WPF控件Grid的布局和C1FlexGrid的多选应用
使用 Grid.Column和Grid.Row布局,将多个C1FlexGrid布局其中,使用各种事件来达到所需效果,点击复选框可以加载数据到列表,移除列表的数据,自动取消复选框等 移除复选框的要注意!!!&am…...
Postman配置环境变量
🍅 点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快 Postman是一套比较方便的接口测试工具,但我们在使用过程中,可能会出现创建了API请求,但API的URL会随着服务器IP地址的变化而改…...
import语句详解
在 Java 中,import 语句用于引入其他包中的类、接口或静态成员,以便在当前源文件中直接使用它们,而不需要写完整的类名(包括包名)。以下是 import 语句的详细解释和使用方法: 一、import语句的基本概念 定…...
数据结构与算法之二叉树: LeetCode 199. 二叉树的右视图 (Ts版)
二叉树的右视图 https://leetcode.cn/problems/binary-tree-right-side-view/ 描述 给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。 示例 1 输入:root [1,2,3,nu…...
CentOS7修改Docker默认存储路径
当你使用Docker时,Docker的默认配置是将镜像、容器和卷存储在系统/var/lib/docker/目录下,如果docker镜像安装的太多会导致磁盘不够,你可以尝试以下方法来释放空间: 清理无用的镜像和容器:使用docker命令删除不再使用…...
宝塔面板使用 GoAccess Web 日志分析教程
宝塔面板是一个简单方便的服务器运维面板,但其网站统计功能是收费的。而 GoAccess 是一个用 C 编写的免费开源 Web日志分析器,本文将介绍如何在宝塔面板中开启 GoAccess Web 日志分析功能。 内容索引 下载安装 GoAccess在宝塔面板中添加日志切割的计划任务将 Web 日志输出到…...
【FPGA】时序约束与分析
设计约束 设计约束所处环节: 约束输入 分析实现结果 设计优化 设计约束分类: 物理约束:I/O接口约束(例如引脚分配、电平标准设定等物理属性的约束)、布局约束、布线约束以及配置约束 时序约束:设计FP…...
c++入门之 命名空间与输入输出
1、命名空间 1.1使用命名空间的原因 先看一个例子: #include <iostream>int round 0;int main() {printf("%d", round);return 0; }请问,这个程序能跑起来吗? 答案是否定的 原因是,当我们想创建一个全局变量 …...
【zotero】解决无法参考文献交叉跳转、相关参考文献插件推荐
无法跳转 参考大佬文章的方法: https://blog.csdn.net/air__Heaven/article/details/137470687 但是有可能有时候又跳不了了,可以多多执行一下 zotero-citation插件 github地址 : https://github.com/MuiseDestiny/zotero-citation cl ht…...
《深度学习模型在鸿蒙分布式框架下的跨设备高效之旅》
在人工智能领域,深度学习模型的训练与推理通常需要强大的计算资源和大量的数据支持。而鸿蒙系统的分布式框架为解决这一问题提供了新的思路和方法,使得深度学习模型能够在多个设备之间实现高效的训练与推理。 鸿蒙分布式框架概述 鸿蒙系统是一款面向万…...
不同方式获取音频时长 - python 实现
DataBall 助力快速掌握数据集的信息和使用方式,会员享有 百种数据集,持续增加中。 需要更多数据资源和技术解决方案,知识星球: “DataBall - X 数据球(free)” -------------------------------------------------------------…...
用python实现烟花代码,完整代码拿走不谢
有时候用python实现一些有趣的代码,既有趣,又能提升知识 使用Python实现动态烟花代码 效果如下: 不废话,直接上代码: import pygame from random import randint, uniform, choice import mathvector pygame.math…...
[OPEN SQL] 限定选择行数
本次操作使用的数据库表为SCUSTOM,其字段内容如下所示 航班用户(SCUSTOM) 该数据库表中的部分值如下所示 指定查询多少行数据,我们可以使用语法UP TO n ROWS来实现对数据前n项的查询 语法格式 SELECT * FROM <dbtab> UP TO n ROWS 参数说明 db…...
【入门级】计算机网络学习
网络安全:前端开发者必知:Web安全威胁——XSS与CSRF攻击及其防范-CSDN博客 三次握手四次挥手:前端网络—三次握手四次挥手_前端三次握手-CSDN博客 http协议和https协议的区别:前端网络—http协议和https协议的区别-CSDN博客 网…...
Redis 安装与 Spring Boot 集成指南
安装 Redis 和将其与 Spring Boot 应用集成是构建高效缓存解决方案的常见步骤。以下是详细的指南,帮助你在本地环境中安装 Redis,并在 Spring Boot 项目中配置和使用它。 1. 安装 Redis Windows 环境 Redis 官方并不直接支持 Windows,但你…...
基于 Python 和 OpenCV 的人脸识别上课考勤管理系统
博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…...
【c/c++】 windows下调用putty
windows和linux系统存在差异,同样的数据在两边的终端行为都不一样,就很头疼。 例如:换行符,win下是\r\n 而linux下是\n 又或者win下使用vi 好在找到了解决方案 1、通过第三方程序GoTTY(支持windows和Linux&#x…...
JVM常见面试题
1.内存泄漏与内存溢出的区别 内存泄漏是指不再使用的对象无法得到及时的回收,持续占用内存空间,从而导致系统内存逐渐减少,系统性能下降,最终可能引发内存溢出内存溢出是指程序在运行时需要分配内存,但 JVM 没有足够的内存可以分配(超出可用内存大小),最终导致内存分配…...
手机租赁系统开发解决方案与市场趋势分析
内容概要 手机租赁系统开发正如一场技术与商业的双重舞会,双方时而相互辉映,时而却也是一场较量。在这片快速变幻的市场中,了解当前的技术实现与挑战尤为重要。例如,系统架构的选择、数据安全性以及用户体验设计都可能成为企业发…...
基于Qt的OFD阅读器开发原理与实践
摘要 本文详细探讨了基于Qt开发OFD阅读器的原理与实践。通过解析OFD文件格式、构建文档结构、实现页面渲染、处理用户交互以及进行性能优化,本文展示了如何使用Qt框架开发一个功能强大、性能优异的OFD阅读器。文章还提供了示例代码和未来发展方向,为开发…...
Redis实现高效的负载均衡算法
1. Redis存储设计 我们需要在 Redis 中存储以下信息: 配置列表(List<Config>):存储所有配置项。总权重:存储所有配置的总权重。当前轮询状态:存储当前的轮询状态(如当前随机值或索引&am…...
spring依赖注入
一、 注入方式 1. 构造器注入 构造器注入通过构造方法来注入依赖的对象。当Spring容器创建Bean时,会通过构造器来传递依赖对象。这种方式是最推荐的方式,因为它可以确保依赖对象在创建时已经完全注入。 示例: Component public class Car…...
流浪猫流浪狗领养PHP网站源码
源码介绍 流浪猫流浪狗领养PHP网站源码,适合做猫狗宠物类的发信息发布。当然其他信息发布也是可以的。 导入数据库,修改数据库配置/application/database.php 设置TP伪静态,设置运行目录, 后台:/abcd.php/dashboard?…...
ffmpeg 编译遇到的坑
makeinfo: error parsing ./doc/t2h.pm: Undefined subroutine &Texinfo::Config::set_from_init_file called at ./doc/t2h.pm line 24. 编译选项添加: --disable-htmlpages...
灵活运用事务回滚,快捷处理多张数据表格
各位编程宝子们(尤其是对MySQL了解不多的宝子们)在使用关系表处理时,有时候会希望简单一次性解决多张表的数据处理,但又有时候无从下手。其实有时候掌握数据的事务和回滚便可以简单解决这些事情,接下来我将以一个学生信…...
MyBatis 性能优化
1. 引言 1.1 什么是 MyBatis? MyBatis 是一款流行的 Java 持久层框架,能够将 Java 对象与 SQL 数据库映射起来。与传统的 JDBC 不同,MyBatis 提供了灵活的 SQL 映射功能,使开发者可以专注于业务逻辑,而无需编写冗长的…...
【python基础】python内置函数 zip用法介绍
zip() 是 Python 中非常有用的内建函数,能够将多个可迭代对象(如列表、元组、字符串等)打包成一个迭代器,它将对应位置的元素组合成元组,并返回一个由这些元组组成的迭代器。通常用于并行处理多个可迭代对象。 1. 基本…...
Unity Android AAB包GooglePlay上线备忘
aab GooglePlay要求新上线的App必须使用aab格式提交,在Unity Build Settings中勾选Build App Bundle 选项即可;或者在代码中设置: EditorUserBuildSettings.buildAppBundle true; 安装测试 https://developer.android.com/tools/bundlet…...
基于springboot的课程作业管理系统源码(springboot+vue+mysql)
风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的课程作业管理系统。项目源码以及部署相关请联系风歌,文末附上联系信息 。 项目简介: 可以管理首页、个人中心…...
JVM生产环境常用参数配置及调优建议
一、生产常用参数配置 JAVA_OPTS="-server -Xms4G -Xmx4 -Xmn2G -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:InitiatingHeapOccupancyPercent=45 -XX:ParallelGCThreads=8 -XX:ConcGCThreads=8 -XX:G1HeapRegionSize=16m -XX:MaxGCCount=10 -XX:MetaspaceSize=256m -XX:…...
vue 实现打包并同时上传至服务器端
将 publish_script 及以下文件 upload.server.js 添加到 主文件下,与 src 同级别 具体操作步骤: 1、安装 npm install scp2 2、将下面两条命令加入至 package.json 的 scripts 中 "upload": "node publish_script/upload.server.js&q…...
深入探索AI核心模型:CNN、RNN、GAN与Transformer
在人工智能的飞速发展中,众多深度学习模型和算法不断涌现,推动了许多领域的进步。特别是在图像识别、自然语言处理、生成建模等方向,AI模型的应用越来越广泛。本文将介绍几种最常用的AI模型,包括卷积神经网络(CNN&…...
【Elasticsearch】配置分片分配到指定节点
配置分片分配到指定节点 参考文章:https://www.elastic.co/guide/en/elasticsearch/reference/current/shard-allocation-filtering.html 两种方式:根据节点属性分配和根据节点名称分配。 测试环境 tar xvf elasticsearch-7.17.25-linux-x86_64.tar.gz…...
【贵州省】乡镇界arcgis格式shp数据乡镇名称和编码内容下载测评
shp数据字段乡镇名称和编码,坐标是wgs84,数据为SHP矢量格式,下载下来直接加载进ArcMap即可使用 下载地址:https://download.csdn.net/download/zhongguonanren99/14928126...
EasyExcel上传校验文件错误信息放到文件里以Base64 返回给前端
产品需求: 前端上传个csv 或 excel 文件,文件共4列,验证文件大小,类型,文件名长度,文件内容,如果某行某个单元格数据验证不通过,就把错误信息放到这行第五列,然后把带有…...
Python 植物大战僵尸
文章目录 效果图项目结构实现思路源代码 效果图 项目结构 实现思路 下面是代码的实现思路: 导入必要的库和模块:首先,我们导入了Python的os、time库以及pygame库,还有植物大战僵尸游戏中用到的各个植物和僵尸的类。 初始化游戏和…...
继承(7)
大家好,今天我们继续来学习一下继承的知识,这方面需要大家勤动脑才能理解,那么我们来看。 1.9 protected关键字 在类和对象章节中,为了实现封装特性,java中引入访向限定符,主要限定:类或者类中成员能否在类外和其他包中被访问. …...
UML(统一建模语言)
目录 一、用例图(Use Case Diagram) 二、类图(Class Diagram) 2.1、泛化(Generalization) 2.2、实现(Realization) 2.3、关联(Association) 2.4、聚合&…...
【面试题】技术场景 7、定位系统瓶颈
系统瓶颈定位方法总述 面试官询问如何快速定位系统瓶颈,旨在考察线上调试经验。主要方法包括: 压测:在项目上线前找出系统瓶颈并修复。监控工具或链路追踪工具:项目上线后用于实时监控或评测找瓶颈。Arthas(原阿尔萨…...
计算机网络之---传输层的功能
传输层的功能 传输层是 OSI(开放系统互联)七层模型中的第四层,位于应用层和网络层之间。传输层的主要作用是提供端到端的通信服务,确保数据在不同设备之间的可靠传输。它主要负责将来自上层(应用层)的数据拆…...
设计一个利用事务特性可以阻塞线程的排他锁,并且通过注解和 AOP 来实现
设计思路: 利用数据库表记录锁标识:通过唯一标识符(如方法名 参数),我们可以在数据库中插入一条记录,表示当前方法正在执行。这条记录需要记录插入时间。 注解:通过注解标识哪些方法需要加锁&a…...