uml 是什么?

UML 全称是 user mode linux,是一种可以将内核作为用户态程序直接运行的功能。UML 内核不会直接与硬件交互,实际上它与普通程序一样与一个真正的 linux 内核(又称为宿主机内核)交互。

程序能够在 UML 中像在普通的内核中一样运行。

其架构示意图如下:

                     +----------------+| Process 2 | ...| +-----------+----------------+| Process 1 | User-Mode Linux|+----------------------------+|       Linux Kernel         |    +----------------------------+|         Hardware           |    +----------------------------+

上图来源于内核 Documentation 下的帮助文档。通过上图我们可以看到 User-Mode Linux 下层为真正的宿主机 linux 内核,它借由宿主机内核与硬件进行交互。

UML 的第一手资料在哪里?

内核源码目录中 Documentation 的如下目录中有对 uml 的详细说明。

./virtual/uml/UserModeLinux-HOWTO.txt

备注:笔者使用的内核为 4.19 的内核,不同的内核版本路径可能有差异。

UML 内核编译使用

  1. make ARCH=um defconfig

    生成 uml 的默认配置

  2. make ARCH=um -j16

    编译 uml 内核

  3. 创建根文件系统

    1. dd 创建根文件系统文件

    2. mkfs.ext4 对根文件系统文件进行格式化

    3. 挂载根文件系统到 /mnt 中

    4. 使用 busybox 制作一个简单的根文件系统

      etc 目录中重要的文件内容如下:

     / # cd etc//etc # lsfstab    init.d   inittab/etc # cat fstab proc /proc proc defaults 0 0tmpfs /tmp tmpfs defaults 0 0sysfs /sys sysfs defaults 0 0tmpfs /dev tmpfs defaults 0 0/etc # cat init.d/rcS #!/bin/sh/bin/mount -amkdir -p /dev/ptsmount -t devpts devpts /dev/ptsecho /sbin/mdev > /proc/sys/kernel/hotplugmdev -s/etc # cat inittab ::sysinit:/etc/init.d/rcS::respawn:-/bin/sh::askfirst:-/bin/sh::ctrlaltdel:/bin/umount -a -r
  1. 安装编译出的内核模块到跟文件系统中
 sudo mount rootfs.img /mnt -o loopsudo make modules_install INSTALL_MOD_PATH=/mnt ARCH=um

安装 uml 实用程序

执行如下命令安装 uml-utilities 使用程序,这个包中包括了 tunctl、uml_net、uml_switch 等程序。

sudo apt-get install uml-utilities

运行 UML 内核

UML 内核编译完成后会生成 linux 这个可执行文件,我们直接执行 ./linux 的时候,它会尝试挂载当前目录中名为 root_fs 的文件名。不需要用 root 权限来运行 linux 程序。

如果你的根文件系统不叫 root_fs,你需要在运行命令行中指定 ubd0=xx 来运行 uml 内核。

运行示例如下:

[longyu@debian-10:07:55:38] linux-source-4.19 $ ./linux
Core dump limits :soft - 0hard - NONE
Checking that ptrace can change system call numbers...OK
Checking syscall emulation patch for ptrace...OK
Checking advanced syscall emulation patch for ptrace...OK
Checking environment variables for a tempdir...none found
Checking if /dev/shm is on tmpfs...OK
Checking PROT_EXEC mmap in /dev/shm...OK
Adding 14761984 bytes to physical memory to account for exec-shield gap
Linux version 4.19.98 (longyu@debian-10) (gcc version 8.3.0 (Debian 8.3.0-6)) #3 Sat Aug 8 17:41:44 CST 2020
Built 1 zonelists, mobility grouping on.  Total pages: 11634
Kernel command line: root=98:0
Dentry cache hash table entries: 8192 (order: 4, 65536 bytes)
Inode-cache hash table entries: 4096 (order: 3, 32768 bytes)
Memory: 27196K/47184K available (2891K kernel code, 706K rwdata, 844K rodata, 113K init, 166K bss, 19988K reserved, 0K cma-reserved)
NR_IRQS: 15
clocksource: timer: mask: 0xffffffffffffffff max_cycles: 0x1cd42e205, max_idle_ns: 881590404426 ns
Calibrating delay loop... 3540.58 BogoMIPS (lpj=17702912)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 512 (order: 0, 4096 bytes)
Mountpoint-cache hash table entries: 512 (order: 0, 4096 bytes)
Checking that host ptys support output SIGIO...Yes
Checking that host ptys support SIGIO on close...No, enabling workaround
devtmpfs: initialized
random: get_random_u32 called from bucket_table_alloc+0x169/0x196 with crng_init=0
Using 2.6 host AIO
clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
futex hash table entries: 256 (order: 0, 6144 bytes)
NET: Registered protocol family 16
clocksource: Switched to clocksource timer
VFS: Disk quotas dquot_6.6.0
VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
NET: Registered protocol family 2
tcp_listen_portaddr_hash hash table entries: 256 (order: 0, 4096 bytes)
TCP established hash table entries: 512 (order: 0, 4096 bytes)
TCP bind hash table entries: 512 (order: 0, 4096 bytes)
TCP: Hash tables configured (established 512 bind 512)
UDP hash table entries: 256 (order: 1, 8192 bytes)
UDP-Lite hash table entries: 256 (order: 1, 8192 bytes)
NET: Registered protocol family 1
console [stderr0] disabled
mconsole (version 2) initialized on /home/longyu/.uml/mIEkRV/mconsole
Checking host MADV_REMOVE support...OK
workingset: timestamp_bits=62 max_order=13 bucket_order=0
io scheduler noop registered
io scheduler deadline registered (default)
io scheduler mq-deadline registered (default)
io scheduler kyber registered
NET: Registered protocol family 17
Initialized stdio console driver
Console initialized on /dev/tty0
console [tty0] enabled
Initializing software serial port version 1
console [mc-1] enabled
EXT4-fs (ubda): INFO: recovery required on readonly filesystem
EXT4-fs (ubda): write access will be enabled during recovery
EXT4-fs (ubda): recovery complete
EXT4-fs (ubda): mounted filesystem with ordered data mode. Opts: (null)
VFS: Mounted root (ext4 filesystem) readonly on device 98:0.
devtmpfs: mounted
This architecture does not have kernel memory protection.
Run /sbin/init as init process
Bad inittab entry at line 6
random: fast init donePlease press Enter to activate this console. random: crng init done/ #

上述示例中,linux 内核正常运行,最后我们按任意键它会进入终端中。

根文件系统挂载为 ro 的问题

如果你仔细阅读了我上面运行 linux 内核的示例,你能够看到如下输出:

VFS: Mounted root (ext3 filesystem) readonly on device 98:0.

这个输出表明根文件系统被挂载为了 ro,这意味着我们不能在其中创建任何文件。

网上搜索了下相关内容,发现这个问题可能是根文件系统的问题,运行 fsck 修复了下重新执行后仍然有相同的问题

最终通过执行如下命令重新将根文件系统挂载为 rw

mount / -o remount,rw

可以将这个命令写入到 etc/init.d 中的 rcS 文件中,这样在启动的时候就会自动执行了。

uml 内核网络配置

首先从内核帮助文档中了解到,uml 虚拟机能够通过下面中方式与其它主机交换网络包。

  • ethertap
  • TUN/TAP
  • Multicast
  • a switch daemon
  • slip
  • slirp
  • pcap

使用 ethertap type 类型配置网络的坑

通过查看内核帮助信息,只要使用添加如下命令就能够使用 ethertap 类型配置 uml 的网络。

       eth0=ethertap,tap0,fe:fd:0:0:0:1,192.168.0.254

这里还需要在宿主机上创建 tap 口,执行如下命令进行创建:

  1. mknod /dev/tap0 c 36 16
  2. 启动 linux 进入终端中执行 ifconfig eth0 up 命令

执行后报如下错误:

/ # ifconfig eth0 up
etap_tramp : uml_net failed
helper_wait : process 6511 exited with status 0x100
* ifconfig tap0 arp mtu 1500 192.168.0.254 netmask 255.255.255.255 up
* bash -c echo 1 > /proc/sys/net/ipv4/ip_forward
open: No such device or address
etap_tramp failed - err = 10
ifconfig: SIOCSIFFLAGS: No child processes

根据这个报错信息,在内核源码中搜索了下相应的源码,发现是在 ethertap_user.c 中打印的报错,大致浏览了下,没有发现异常点。

进行了如下检查:

  1. 检查 uml_net 的权限(是否设定 suid)
  2. 检查 tap 口的权限

uml_net 程序给 other 添加可执行权限,/dev/tap0 修改用户与属组为我执行 linux 程序的用户,再次运行报相同的错误。

重新 check 内核中的帮助文档,这次注意到了如下信息:

  You also need to make sure that the host kernel has ethertap support.If ethertap is enabled as a module, you apparently need to insmodethertap once for each ethertap device you want to enable.  So,host#insmod ethertapwill give you the tap0 interface.  To get the tap1 interface, you needto runhost#insmod ethertap unit=1 -o ethertap1

原来还需要在主机系统中加载 ethertap 驱动,尝试 modprobe ethertap 结构报错找不到相应的驱动。

以关键词 ethertap 搜索内核源码中所有 Makefile,只在 arch/um/ 中搜到了相应的文件,这表明我主机上的 linux 内核并没有这个驱动。

网上搜索,找到了如下链接:

linux-2.4 Documentation/networking/ethertap.txt

阅读内容发现 ethertap 在 2.5.x 内核中已经被移除了,取而代之的是 tun/tap 驱动,既然没有这个驱动,那就用 tun/tap 这种类型来设定 uml 的网络。

使用 tuntap 类型配置 uml 的网络

最简单的配置方法是设定 uml_net 程序的 setuid 权限让 uml_net 程序来帮我们设定宿主机上的配置。

uml_net 的配置过程包括加载 tun.ko 模块(如果需要的话),配置接口,设定 ip 转发、路由与 arp 代理。

使用 uml_net 的环境下命令格式如下:

      eth <n> =tuntap,,, <IP address>

一个具体的命令示例如下:

sudo ./linux eth0=tuntap,,,192.168.0.254

进入终端后执行 ifconfig eth0 up 有如下输出信息:

/ # ifconfig eth0 up
* modprobe tun
* ifconfig tap3 192.168.0.254 netmask 255.255.255.255 up
* bash -c echo 1 > /proc/sys/net/ipv4/ip_forward
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 3E:EF:18:C8:EC:E6  UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1RX packets:55 errors:0 dropped:19 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:1000 RX bytes:8265 (8.0 KiB)  TX bytes:0 (0.0 B)Interrupt:5

以 * 开始的输出信息是 uml_net 执行的命令的输出,可以看到它与我在上面描述的 uml_net 的配置过程一致。

接口 up 起来后配置 ip 地址,然后 ping tap 口的 ip 能够 ping 通了。操作过程如下:

/ # ifconfig eth0 192.168.0.1
* route add -host 192.168.0.1 dev tap3
* bash -c echo 1 > /proc/sys/net/ipv4/conf/tap3/proxy_arp
/ # ping 192.168.0.254
PING 192.168.0.254 (192.168.0.254): 56 data bytes
64 bytes from 192.168.0.254: seq=0 ttl=64 time=0.974 ms
64 bytes from 192.168.0.254: seq=1 ttl=64 time=0.643 ms

同样以 * 开头的是 uml_net 配置网络运行的命令的输出信息,这里添加了一条主机路由并开启了 tap3 的 arp 代理。

arp proxy 能够让一个系统响应不同系统的 arp 请求。这里就是用宿主机上的 tap3 口响应 linux 命令内部的 arp 请求。

要 ping 通其它网关的 ip 地址需要设定路由,执行过程记录如下:

/ # route add default gw 192.168.0.254
/ # route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         192.168.0.254   0.0.0.0         UG    0      0        0 eth0
192.168.0.0     *               255.255.255.0   U     0      0        0 eth0
/ # ping 192.168.1.4
PING 192.168.1.4 (192.168.1.4): 56 data bytes
64 bytes from 192.168.1.4: seq=0 ttl=64 time=1.097 ms
64 bytes from 192.168.1.4: seq=1 ttl=64 time=0.712 ms

可以看到配置了默认网关后,在 linux 程序内部能够 ping 通本地主机上其它网段的 ip 地址。

使用 uml_net 自动配置还是手动配置

上文中,我描述了使用 uml_net 自动配置 tap 口网络的方式,这种方式非常方便,适合初学者,对一些老鸟来说,完全可以手动配置网络,这无非是要手动加载驱动、创建 tap 口等等操作,linux 的帮助文档中也有详细的描述,应该不成问题。

关于 tap 口、网桥的配置可以参考如下博客:

tun 与 tap 设备,网桥、VLAN、bonding 的学习

共享文件系统

uml 中可以挂载主机中的 nfs 共享文件系统,或者通过其它的一些虚拟共享文件系统来实现。

gdb 调试用户态内核的一些问题

uml linux 作为一个用户态程序来执行可以非常方便的使用 gdb 调试。理论上应该是这样没错,但是直接调试的过程中却遇到了一些问题,在这里也记录一下。

SIGSEGV 与 SIGUSR1 信号

单步调试发现会有段错误报错,相关信息如下:

Thread 1 "linux" received signal SIGSEGV, Segmentation fault.__memset_avx2_unaligned_erms () at ../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S:200
200 ../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S: 没有那个文件或目录.
(gdb)
hard_handler (sig=11, si=0x603cfbf0 <cpu0_irqstack+7152>, p=0x603cfac0 <cpu0_irqstack+6848>) at arch/um/os-Linux/signal.c:164

可以在 gdb 中设定 SIGSEGV 与 SIGUSR1 信号的处理方式来让程序不在收到这些信号的时候停下来。

具体命令如下:

(gdb) handle SIGSEGV pass nostop noprint
Signal        Stop  Print   Pass to program Description
SIGSEGV       No    No  Yes     Segmentation fault
(gdb) handle SIGUSR1 pass nostop noprint
Signal        Stop  Print   Pass to program Description
SIGUSR1       No    No  Yes     User defined signal 1

设定了上述内容后调试发现,在访问内存的时候会收到 SIGIO 信号并执行 hard_handler 处理此信号。

调试过程记录如下:

(gdb) frame 2
#2  0x00000000600810f9 in elf_header_check (info=<optimized out>) at kernel/module.c:2835
2835        if (memcmp(info->hdr->e_ident, ELFMAG, SELFMAG) != 0
(gdb) bt
#0  hard_handler (sig=29, si=0x603cfaf0 <cpu0_irqstack+6896>, p=0x603cf9c0 <cpu0_irqstack+6592>) at arch/um/os-Linux/signal.c:164

使用上面的方法设定 nopass 之后发现也不行,这个应该跟 um 的机制有关,它的所有访存操作可能都是通过发送 SIGIO 信号来完成的。

gdb 中启动 uml linux 程序后当程序启动完成后按下 Contrl+C 后查看不同线程的堆栈,有如下输出:

Thread 4 (Thread 0x7ffff7db9b80 (LWP 19489)):
#0  0x00007ffff7ea97e4 in __GI___poll (fds=0x61cce6a0, nfds=1, timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:29
#1  0x000000006002cff7 in write_sigio_thread (unused=<optimized out>) at arch/um/os-Linux/sigio.c:61
#2  0x00007ffff7eb44cf in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95Thread 3 (Thread 0x7ffff7db9b80 (LWP 19488)):
#0  0x00007ffff7ea97e4 in __GI___poll (fds=0x60485430 <kernel_pollfd>, nfds=1, timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:29
#1  0x00000000600285a8 in ubd_read_poll (timeout=<optimized out>) at arch/um/drivers/ubd_user.c:71
#2  0x0000000060028129 in io_thread (arg=<optimized out>) at arch/um/drivers/ubd_kern.c:1559
#3  0x00007ffff7eb44cf in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95Thread 2 (Thread 0x7ffff7db9b80 (LWP 19487)):
#0  syscall () at ../sysdeps/unix/sysv/linux/x86_64/syscall.S:38
#1  0x000000006002a96d in io_getevents (min_nr=<optimized out>, nr=<optimized out>, timeout=<optimized out>, events=<optimized out>, ctx_id=<optimized out>)at arch/um/os-Linux/aio.c:109
#2  aio_thread (arg=<optimized out>) at arch/um/os-Linux/aio.c:109
#3  0x00007ffff7eb44cf in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95Thread 1 (Thread 0x7ffff7db9b80 (LWP 19479)):
#0  0x00007ffff7f8d50e in __libc_read (fd=0, buf=0x603cdc8f, nbytes=1) at ../sysdeps/unix/sysv/linux/read.c:26
#1  0x000000006001fb51 in generic_read (fd=<optimized out>, c_out=<optimized out>, unused=<optimized out>) at arch/um/drivers/chan_user.c:26
#2  0x000000006001f7fd in chan_interrupt (line=0x0, irq=1614601359) at arch/um/drivers/chan_kern.c:525
#3  0x0000000060020186 in line_interrupt (irq=<optimized out>, data=<optimized out>) at arch/um/drivers/line.c:25
#4  0x000000006006733c in __handle_irq_event_percpu (desc=0x0, flags=0x603cdc8f) at kernel/irq/handle.c:149
#5  0x0000000060067433 in handle_irq_event_percpu (desc=0x603e5200 <irq_desc+512>) at kernel/irq/handle.c:189
#6  0x0000000060067499 in handle_irq_event (desc=0x603e5200 <irq_desc+512>) at kernel/irq/handle.c:206
#7  0x000000006006a65f in handle_edge_irq (desc=0x603e5200 <irq_desc+512>) at kernel/irq/chip.c:797
#8  0x0000000060066c8a in generic_handle_irq_desc (desc=<optimized out>) at ./include/linux/irqdesc.h:155
#9  generic_handle_irq (irq=<optimized out>) at kernel/irq/irqdesc.c:639
#10 0x000000006001a702 in do_IRQ (irq=<optimized out>, regs=<optimized out>) at arch/um/kernel/irq.c:423
#11 0x000000006001a7b8 in irq_io_loop (regs=<optimized out>, irq=<optimized out>) at arch/um/kernel/irq.c:52
#12 sigio_handler (sig=<optimized out>, unused_si=<optimized out>, regs=<optimized out>) at arch/um/kernel/irq.c:95
#13 0x000000006002de27 in sig_handler_common (sig=29, si=<optimized out>, mc=0x0) at arch/um/os-Linux/signal.c:52
#14 0x000000006002dd09 in unblock_signals () at arch/um/os-Linux/signal.c:307
#15 unblock_signals () at arch/um/os-Linux/signal.c:259
#16 0x000000006001b1da in arch_local_irq_enable () at ./arch/um/include/asm/irqflags.h:25
#17 arch_cpu_idle () at arch/um/kernel/process.c:210
#18 0x00000000602ea702 in default_idle_call () at kernel/sched/idle.c:93
#19 0x00000000600586d7 in cpuidle_idle_call () at kernel/sched/idle.c:153
#20 do_idle () at kernel/sched/idle.c:263
#21 0x000000006005896d in cpu_startup_entry (state=<optimized out>) at kernel/sched/idle.c:369
#22 0x00000000602e6aa7 in rest_init () at init/main.c:441
#23 0x0000000060001b9e in start_kernel () at init/main.c:737
--Type <RET> for more, q to quit, c to continue without paging--
#24 0x0000000060003427 in start_kernel_proc (unused=<optimized out>) at arch/um/kernel/skas/process.c:28
#25 0x000000006001ad62 in new_thread_handler () at arch/um/kernel/process.c:133
#26 0x000000006001d9b3 in uml_finishsetup () at arch/um/kernel/um_arch.c:234
#27 0x0000000000000000 in ?? ()

这里总共有 4 个线程,第 1 个线程正在等用户从终端输入,剩下的 3 个线程与 io 事件处理相关。

ps 可以看到有多个名为 linux 的进程。

[longyu@debian-10:11:50:26] backup $ ps aux | grep linux
longyu   18535  1.0  1.7 166100 137188 pts/3   S+   11:40   0:08 gdb ./linux
longyu   19479  0.5  0.1  35212 14684 pts/3    t    11:46   0:02 /home/longyu/linux-source-4.19/linux
longyu   19487  0.0  0.1  35212 14684 pts/3    t    11:47   0:00 /home/longyu/linux-source-4.19/linux
longyu   19488  0.0  0.1  35212 14684 pts/3    t    11:47   0:00 /home/longyu/linux-source-4.19/linux
longyu   19489  0.0  0.1  35212 14684 pts/3    t    11:47   0:00 /home/longyu/linux-source-4.19/linux
longyu   19490  0.0  0.0   3880  1808 pts/3    t    11:47   0:00 /home/longyu/linux-source-4.19/linux
longyu   19502  0.0  0.0   2580   308 pts/3    t    11:47   0:00 /home/longyu/linux-source-4.19/linux

尝试再用 gdb -p attach 到其它进程中,发现会失败,失败信息记录如下:

Attaching to process 19502
warning: process 19502 is already traced by process 19479
ptrace: 不允许的操作.

报错信息表明,其它的 linux 程序已经被 19479 这个父程序使用 ptrace 跟踪了,gdb 再次跟踪就失败了。

如果我们要先运行 linux 程序,然后使用 gdb -p attach 上去,我们需要注意要 attach 到父程序上。

总结

uml linux 能够用来调试内核,便于我们去了解内核代码运行的细节,但 uml linux 也存在一些问题,它的官方文档已经很久没有更新过了,其中有一些在新的内核中不适用的内容,同时也必须指出的是并非所有的内核都能正常使用 uml。

debian 10 系统运行 uml 与网络配置相关推荐

  1. debian安vs_在Debian 10系统下安装和更新Visual Studio Code的方法

    本文介绍在Debian 10 Linux操作系统下安装Visual Studio Code(VS Code)编辑器的方法,同时附上更新的命令. 在Debian 10下安装Visual Studio C ...

  2. Debian 7.x 安装教程、网络配置、软件源配置、磁盘分区、LVM、U盘安装、网络安装...

    目录 一.准备安装Debian系统      1.1Debian简介          1.1.1介绍Debian版本          1.1.2Debian的正式发音          1.1.3 ...

  3. Debian 10系统最小化安装

    Debian 10最小化安装 一.Debian系统介绍 广义的Debian是指一个致力于创建自由操作系统的合作组织及其作品,由于Debian项目众多内核分支中以Linux宏内核为主,而且 Debian ...

  4. VMware安装Ubuntu 18.04虚拟机(镜像下载、硬盘分区、创建虚拟机、安装系统、桥接模式网络配置)

    1. VMware安装 安装VMware,Player免费,而且功能足够个人开发使用.(Pro的主要区别在于可以同时运行多个虚拟机,而Player只能同时运行一个) VMware Workstatio ...

  5. 首次使用树莓派2(安装系统+SSH+VNC+无线网络配置)

    准备移植视觉程序到树莓派上运行,所以需要先在树莓派上搭建运行环境.本文将记录首次使用树莓派的基本过程,也是必经之路. 因为树莓派买回来的时候就自己带了一张光碟,里面有安装系统需要的工具和系统. 需要用 ...

  6. 优麒麟系统Ubuntu Kylin的网络配置

    优麒麟系统Ubuntu Kylin如何进行网络连接与配置,今天小编就的教你们几个简单方法,分分钟轻松搞定,关注收藏再也不用为上网而困扰. 无线网络配置 如果您的计算机启用了无线,则可在处于无线网线覆盖 ...

  7. Linux系列一 VMware 中 Fedora系统的安装与网络配置

    之前一篇文章,简单地总结了自己的Linux假期培训课程.因为自己也打算开始学习Linux,所以就在这里写点东西,记录自己的学习历程,如果也能给大家带去一点帮助的话,甚是欣慰.能力时间有限,难免有疏漏的 ...

  8. 树莓派最新版系统烧写和网络配置

    树莓派笔记 1.树莓派烧写篇 2.树莓派WIFI配置篇 3.树莓派ping外网 4.树莓派git篇 5.参考 1.树莓派烧写篇 目前烧写最新版本32位系统(2022-09-22发布的),默认移除了pi ...

  9. 在x86平台制作龙芯版debian 10系统(mips64el)

    OS: ubuntu 18.04 使用debootstrap制作根文件系统会分成两个阶段.第一阶段是,使用debootstrap命令来下载软件包. 第二阶段是安装软件包. 安装debootstap 等 ...

  10. Windows系统如何备份无线网络配置

    1.以管理员身份运行CMD命令提示符: 2.执行如下命令可将无线网络连接信息导出到当前目录. netsh WLAN export profile key=clear 如下图所示(当前目录为C:\wla ...

最新文章

  1. mxGraph改变图形大小重置overlay位置
  2. Mysqldump参数大全
  3. 京东三级列表页持续架构优化—前端优化实践
  4. 【 D3.js 入门系列 --- 9 】 常见可视化图形
  5. hbase java admin_java连接hbase(一):Admin功能接口表管理
  6. CENTOS7.8忘记ROOT密码,重置密码步骤
  7. 基于route-map的策略路由
  8. Vue 数组封装和组件data定义为函数一些猜测
  9. arcgis js平滑线工具_Arcgis中文字体、平滑线插件使用说明
  10. 动易和php,国内主流CMS对比之织梦内容管理系统VS动易
  11. 等保测评--网络安全等级保护定级指南
  12. 实验1 JavaEE开发环境配置与基础练习(JSP)
  13. 层次分析法(AHP)原理以及应用
  14. 网易面试软件测试面试题
  15. ul阻燃标准有几个等级_UL94阻燃等级介绍及常见误区分析
  16. 解决Chrome浏览器无法加载flash插件的问题
  17. Python图形界面编程
  18. acdream 1401 Lempel-Ziv Compression
  19. 一个纸杯子的测试用例
  20. 简述docx文档格式-CTF竞赛专用

热门文章

  1. 摄像头视频直播方案比较之方案二:乐橙云
  2. 借助Net-Speeder对服务器进行优化
  3. 敏捷管理的利器:故事墙
  4. rust 连接mysql数据库_Dlang、Rust 以及 Golang 数据库操作方式对比
  5. 利用Matplotlib绘制各类图表
  6. 蒟蒻的网络流24题解题记
  7. winform自定义控件无法显示在工具箱中以及显示但使用时出错的解决办法
  8. 90后首次购房心路历程
  9. php一般培训呢多久,php的培训一般课程是多久
  10. 机械考公一般有哪些岗位?