系统启动流程 - 理解modules加载流程

news2025/1/23 4:06:07

​编辑 Hacker_Albert  ·  202

  • linux 启动流程
  • module加载

1.启动过程分为三个部分

  • BIOS 上电自检(POST)
  • 引导装载程序 (GRUB2)
  • 内核初始化
  • 启动 systemd,其是所有进程之父。

在这里插入图片描述

1.1.BIOS 上电自检(POST)

  BIOS stands for Basic Input/Output System. In simple terms, the BIOS loads and executes the Master Boot Record (MBR) boot loader.

  When you first turn on your computer, the BIOS first performs some integrity checks of the HDD or SSD.

  Then, the BIOS searches for, loads, and executes the boot loader program, which can be found in the Master Boot Record (MBR). The MBR is sometimes on a USB stick or CD-ROM such as with a live installation of Linux.

  Once the boot loader program is detected, it’s then loaded into memory and the BIOS gives control of the system to it.

1.2.GRUB2

  Once the POST is complete and the coast is clear, the BIOS probes the MBR (Master Boot Record) for the bootloader and disk partitioning information.

  The MBR is a 512-byte code that is located on the first sector of the hard drive which is usually /dev/sda or /dev/hda depending on your hard drive architecture. Note, however, that sometimes the MBR can be located on a Live USB or DVD installation of Linux.

  There are 3 main types of bootloaders in Linux: LILO, GRUB, and GRUB2. The GRUB2 bootloader is the latest and primary bootloader in modern Linux distributions and informs our decision to leave out the other two which have become antiquated with the passage of time.

  GRUB2 stands for GRand Unified Bootloader version 2. Once the BIOS locates the grub2 bootloader, it executes and loads it onto the main memory (RAM).

  The grub2 menu allows you to do a couple of things. It allows you to select the Linux kernel version that you’d want to use. If you have been upgrading your system a couple of times, you might see different kernel versions listed. Additionally, it gives you the ability to edit some kernel parameters by pressing a combination of keyboard keys.

在这里插入图片描述
  Also, in a dual-boot setup where you have multiple OS installations, the grub menu allows you to select which OS to boot into. The grub2 configuration file is the /boot/grub2/grub2.cfg file. GRUB’s main objective is to load the Linux kernel onto the main memory.

1.3.Kernel Initialization

  The kernel is the core of any Linux system. It interfaces the PC’s hardware with the underlying processes. The kernel controls all the processes on your Linux system. Once the selected Linux kernel is loaded by the bootloader, it must self extract from its compressed version before undertaking any task. Upon self-extracting, the selected kernel mounts the root file system and initializes the /sbin/init program commonly referred to as init.
在这里插入图片描述
  Init is always the first program to be executed and is assigned the process ID or PID of 1. It’s the init process that spawns various daemons & mounts all partitions that are specified in the /etc/fstab file.

  The kernel then mounts the initial RAM disk (initrd) which is a temporary root filesystem until the real root filesystem is mounted. All kernels are located in the /boot directory together with the initial RAM disk image.

1.3.1.initramfs 文件系统

在这里插入图片描述
  Linux操作系统首先要将内核加载到内存。内核驻留于操作系统与应用程序的整个活动周期,其中应用程序(软件)在“用户空间”内运行,位于内核控制之下。

  为了使加载存储器最小化,一些核心Linux程序转化成可加载核心模块形式,可以动态加载系统中。

  initrd系统中的文件在引导阶段可以被核心访问,里面的内容会被挂载成一个loop类型的文件。initrd通常被压缩成gzip类型,在引导的时候由bootloader(LILO、GRUB)来告知核心initrd的位置。在2.6版本内核之后出现了initramfs,它的功能类似initrd,但是它基于CPIO格式,无须挂载就可以展开成一个文件系统。

  initramfs是initrd的替代品。initrd是一个被加载的块设备,内部有ext2一类文件系统的存在,于是由于Linux内核的缓存机制,其中的内容还会被缓存到内存上,造成一定的内存空间浪费。而initramfs本身就是一个tmpfs的RAM disk,拥有最小化的设计,绕过了缓存机制,也消除了多余的内存占用。

1.3.2.加载modules

  内核完成再次系统自检之后,开始采用动态的方式加载每个硬件的模块,这个动态模块大家可以想象成硬件的驱动(默认 Linux 硬件的驱动是不需要手工安装的,如果是重要的功能,则会直接编译到内核当中;如果是非重要的功能,比如硬件驱动会编译为模块,则在需要时由内核调用。不过,如果没有被内核硬件,要想驱动,就需要手工安装个硬件的硬块了。

  模块的全称是动态可加载内核模块,它是具有独立功能的程序,可以被单独编译,但不能独立运行。模块是为内核或其他模块提供功能的代码集合。这些模块可以是 Linux 源码中自带的,也可以是由硬件厂商开发的(可以想象成驱动)。不过内核因为发布时间较长,所以自带的模块可能版本较低,还有一些新硬件可能就不自带模块了,只能由硬件厂商在发布硬件的同时发布新模块。

  也就是说,安装模块一般有两种方法:

  • 第一种方法在编译内核时,手工调整内核模块功能,加入所需的模块。这种方法有一个问题,就是内核必须支持这个硬件或功能才可以通过编译内核加入模块。如果硬件比内核新,内核本身并不支持硬件,就不能通过重新编译内核来加入新的硬件的支持。
  • 第二种方法就是下载厂商发布的新硬件的驱动模块,或下载驱动程序,再编译成驱动模块,然后手工安装。

工具目录:

  • /usr/lib/modprobe.d/
  • /etc/modprobe.d/

1.3.2.1.管理模块实用程序

  • insmod 加载内核模块的简单程序。建议使用modprobe (8), 这更聪明,可以处理模块依赖。
  • rmmod 卸载(可卸载内核模块)的简单程序。建议使用(modprobe -r)。
  • lsmod 列出当前加载的内核模块,(地格式化/proc/modules的内容).
  • depmod 输出适合modprobe实用程序的依赖项列表。(生成modules.dep和映射文件)
    • Linux内核模块可以为其它模块提供提供服务(在代码中使用EXPORT_SYMBOL),这种服务被称作”symbols”。若第二个模块使用了这个symbol,则该模块很明显依赖于第一个模块。这些依赖关系是非常繁杂的。
    • depmod读取在/lib/modules/version 目录下的所有模块,并检查每个模块导出的symbol和需要的symbol,然后创建一个依赖关系列表。默认地,该列表写入到/lib/moudules /version目录下的modules.dep文件中。若命令中的filename有指定的话,则仅检查这些指定的模块(不是很有用)。若命令中提供了version参数,则会使用version所指定的目录生成依赖,而不是当前内核的版本(uname -r 返回的)。
      $ cat /lib/modules/‘uname -r’/modules.dep
  • modinfo 显示有关Linux内核模块的信息
  • modprobe命令用于智能地向内核中加载模块或者从内核中移除模块。
    modprobe可载入指定的个别模块,或是载入一组相依的模块。modprobe会根据depmod所产生的相依关系,决定要载入哪些模块。若在载入过程中发生错误,在modprobe会卸载整组的模块。

1.3.2.2.Kernel module 加载

  使用systemd自动加载模块:

  所有必要模块的加载均由 udev 自动完成。所以,如果不需要使用任何额外的模块,就没有必要在任何配置文件中添加启动时加载的模块。但是,有些情况下可能需要在系统启动时加载某个额外的模块,或者将某个模块列入黑名单以便使系统正常运行。

  内核模块可以在**/etc/modules-load.d/** 下的文件中明确列出,以便systemd在引导过程中加载它们。 每个配置文件都以 /etc/modules-load.d/.conf的样式命名。 配置文件仅包含要加载的内核模块名称列表,以换行符分隔。 空行和第一个非空白字符为#或;的行被忽略。

/etc/modules-load.d/virtio-net.conf:
# Load virtio_net.ko at boot
virtio_net

  手动加载卸载:

  • 1.先将.ko文件拷贝到/lib/module/uname -r/kernel/driver/…目录下,

    根据具体用途的区别分为net、ide、scsi、usb、video、parport、md、block、ata等等。

  • 2.运行depmod -a,更新模块依赖新,主要是更新modules.dep文件

  • 3.运行modprobe加载内核模块

sudo modprobe -v etnaviv

配置模块参数:
1.传递参数的基本方式是使用 modprobe 选项,格式是 key=value:# modprobe module_name parameter_name=parameter_value
2.使用 /etc/modprobe.d/中的文件
要通过配置文件传递参数,在 /etc/modprobe.d/ 中放入任意名称 .conf 文件,加入:
/etc/modprobe.d/myfilename.conf
options modname parametername=parametercontents

  Modules are stored in /usr/lib/modules/kernel_release. You can use the command uname -r to get your current kernel release version.

  黑名单:

  只需将module_blacklist=modname1,modname2,modname3 添加到引导加载程序的内核行中即可。This can also be made permanent by editing /etc/default/grub and adding to the GRUB_CMDLINE_LINUX_DEFAULT variable. For example, in my /etc/default/grub I have:

GRUB_CMDLINE_LINUX_DEFAULT=“quiet splash modprobe.blacklist=nouveau”

1.3.2.3.Kernel module dependencies

  Certain kernel modules sometimes depend on one or more other kernel modules. The /lib/modules/<KERNEL_VERSION>/modules.dep file contains a complete list of kernel module dependencies for the respective kernel version.

  The dependency file is generated by the depmod program, which is a part of the kmod package. Many of the utilities provided by kmod take module dependencies into account when performing operations so that manual dependency-tracking is rarely necessary.

  Linux 中所有的模块都存放在 /lib/modules/kernel_release/modules.dep 文件中,在安装模块时,依赖这个文件査找所有的模块,所以不需要指定模块所在位置的绝对路径,而且也依靠这个文件来解决模块的依赖性。如果这个文件丢失了怎么办?不用担心,使用 depmod 命令会自动扫描系统中已有的模块,并生成 modules.dep 文件。命令格式如下:

[root@localhost ~]# depmod [选项]
#不加选项,depmod命令会扫描系统中的内核模块,并写入modules.dep文件
选项:
-a:扫描所有模块;
-A:扫描新模块,只有有新模块时,才会更新modules.dep文件;
-n:把扫描结果不写入modules.dep文件,而是输出到屏幕上;

  depmod(depend module)可检测模块的相依性,供modprobe在安装模块时使用。depmod 命令会扫描系统中所有的内核模块,然后把扫描结果放入 modules.dep 文件。后续的模块安装或删除就依赖这个文件中的内容。也就是说,如果我们要手工安装一个模块,则需要先把模块复制到指定位置,一般复制至 /lib/modules/kernel_release/kernel/ 目录中,使用 depmod 命令扫描之后,才能继续安装。

1.3.2.3.常用命令:

  To show what kernel modules are currently loaded:
在这里插入图片描述

  • The first column provides the names of currently loaded modules.
  • The second column displays the amount of memory per module in kilobytes.
  • The last column shows the number, and optionally the names of modules that are dependent on a particular module.

  Displaying information about kernel modules:
在这里插入图片描述

  Loading kernel modules at system runtime:

  首先需要把模块复制到指定位置,一般复制到/lib/module/uname -r/kernel目录中,模块的扩展名一般是 *.ko;然后需要执行 depmod 命令扫描这些新模块,并写入 modules.dep 文件;最后就可以利用 modprobe 命令安装这些模块了。命令格式如下:

[root@localhost ~]# modprobe [选项] 模块名
选项:
-f:强制加载模块;
-r:删除模块;

  Unloading kernel modules at system runtime

Unload the relevant kernel module:
# modprobe -r <MODULE_NAME>

  Loading kernel modules automatically at system boot time

Select a kernel module you want to load during the boot process.
The modules are located in the /lib/modules/$(uname -r)/kernel/<SUBSYSTEM>/ directory.
Create a configuration file for the module:
# echo <MODULE_NAME> > /etc/modules-load.d/<MODULE_NAME>.conf

1.3.2.4.调试

  使用 strace 追踪 modprobe 的调用过程,发现 modprobe 并不会使用 modules.dep 文件。可以看到它访问了 modules.dep.bin、modules.alias.bin、modules.symbols.bin、modules.builtin.bin 等文件,它并没有访问 modules.dep 文件。

uos@uos-PC:~$ strace /sbin/modprobe etnaviv 2>&1 | grep open 
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/mips64el-linux-gnuabi64/liblzma.so.5", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/mips64el-linux-gnuabi64/libcrypto.so.1.1", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/mips64el-linux-gnuabi64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/mips64el-linux-gnuabi64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/mips64el-linux-gnuabi64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/etc/modprobe.d", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
openat(AT_FDCWD, "/lib/modprobe.d", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
openat(AT_FDCWD, "/etc/modprobe.d/8821ce.conf", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/modprobe.d/aliases.conf", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/etc/modprobe.d/deepin-screen-recorder.conf", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/modprobe.d/fbdev-blacklist.conf", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/etc/modprobe.d/iwlwifi.conf", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/modules/4.19.0-loongson-3-desktop/modules.softdep", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/modprobe.d/systemd.conf", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/proc/cmdline", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/modules/4.19.0-loongson-3-desktop/modules.dep.bin", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/modules/4.19.0-loongson-3-desktop/modules.alias.bin", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/modules/4.19.0-loongson-3-desktop/modules.symbols.bin", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/lib/modules/4.19.0-loongson-3-desktop/modules.builtin.bin", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/sys/module/etnaviv/initstate", O_RDONLY|O_CLOEXEC) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/sys/module/gpu_sched/initstate", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/sys/module/etnaviv/initstate", O_RDONLY|O_CLOEXEC) = -1 ENOENT (没有那个文件或目录)
openat(AT_FDCWD, "/lib/modules/4.19.0-loongson-3-desktop/kernel/drivers/gpu/drm/etnaviv/etnaviv.ko", O_RDONLY|O_CLOEXEC) = 3
  • /sys/module
    这里有系统中所有模块的信息,不论这些模块是以内联(inlined)方式编译到内核映像文件(vmlinuz)中还是编译为外部模块(ko文件),都可能会出现在 /sys/module 中:

    编译为外部模块(ko文件)在加载后会出现对应的 /sys/module/<module_name>/, 并且在这个目录下会出现一些属性文件和属性目录来表示此外部模块的一些信息,如版本号、加载状态、所提供的驱动程序等;

    编译为内联方式的模块则只在当它有非0属性的模块参数时会出现对应的 /sys/module/<module_name>, 这些模块的可用参数会出现在 /sys/modules//parameters/<param_name> 中,如 /sys/module/printk/parameters/time 这个可读写参数控制着内联模块 printk 在打印内核消息时是否加上时间前缀;所有内联模块的参数也可以由 “<module_name>.<param_name>=” 的形式写在内核启动参数上,如启动内核时加上参数 “printk.time=1” 与 向 “/sys/module/printk/parameters/time” 写入1的效果相同;没有非0属性参数的内联模块不会出现于此。

1.4.Starting Systemd

  The kernel finally loads Systemd, which is the replacement of the old SysV init. Systemd is the mother of all Linux processes and manages among other things mounting of file systems, starting and stopping services to mention just a few.

  Systemd uses the /etc/systemd/system/default.target file to determine the state or target that the Linux system should boot into.

  For a desktop workstation (with a GUI) the default target value is 5 which is the equivalent of run level 5 for the old SystemV init.

  For a server, the default target is multi-user.target which corresponds to run level 3 in SysV init.

  Here’s a breakdown of the systemd targets:

poweroff.target (runlevel 0): Poweroff or Shutdown the system.
rescue.target (runlevel 1): launches a rescue shell session.
multi-user.target (runlevel 2,3,4): Configures the system to a non-graphical (console) multi-user system.
graphical.target (runlevel 5): Set the system to use a graphical multi-user interface with network services.
reboot.target (runlevel 6): reboots the system.

1.4.1.systemd-modules-load.service

  It is an early boot service that loads kernel modules. It reads static configuration from files in /usr/ and /etc/, but also runtime configuration from /run/ and the kernel command line.

  • /usr/lib/systemd/system/systemd-modules-load.service
[Unit]
Description=Load Kernel Modules
Documentation=man:systemd-modules-load.service(8) man:modules-load.d(5)
DefaultDependencies=no
Conflicts=shutdown.target
Before=sysinit.target shutdown.target
ConditionCapability=CAP_SYS_MODULE
ConditionDirectoryNotEmpty=|/lib/modules-load.d
ConditionDirectoryNotEmpty=|/usr/lib/modules-load.d
ConditionDirectoryNotEmpty=|/usr/local/lib/modules-load.d
ConditionDirectoryNotEmpty=|/etc/modules-load.d
ConditionDirectoryNotEmpty=|/run/modules-load.d
ConditionKernelCommandLine=|modules-load
ConditionKernelCommandLine=|rd.modules-load

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/lib/systemd/systemd-modules-load
TimeoutSec=90s

2.systemd-modules-load.service启动失败问题排查

  • 首先,查看哪些服务启动失败:
uos@uos-PC:~$ sudo systemctl --failed    
  UNIT                               LOAD   ACTIVE SUB    DESCRIPTION                                
● lmt-poll.service                   loaded failed failed Laptop Mode Tools - Battery Polling Service
● NetworkManager-wait-online.service loaded failed failed Network Manager Wait Online                
● systemd-modules-load.service       loaded failed failed Load Kernel Modules  
  • journalctl -fp err
uos@uos-PC:~$ sudo journalctl -fp err
-- Logs begin at Mon 2022-01-24 17:07:35 CST. --
1月 25 09:54:14 uos-PC systemd[1]: Failed to start Laptop Mode Tools - Battery Polling Service.
1月 25 09:54:27 uos-PC lightdm[960]: gkr-pam: couldn't unlock the login keyring.
1月 25 09:54:50 uos-PC wpa_supplicant[388]: dbus: wpa_dbus_property_changed: no property SessionLength in object /fi/w1/wpa_supplicant1/Interfaces/1
1月 25 09:55:56 uos-PC wpa_supplicant[388]: dbus: wpa_dbus_property_changed: no property SessionLength in object /fi/w1/wpa_supplicant1/Interfaces/3
1月 25 09:56:52 uos-PC systemd[1]: Failed to start Laptop Mode Tools - Battery Polling Service.
1月 25 09:59:24 uos-PC systemd[1]: Failed to start Laptop Mode Tools - Battery Polling Service.
1月 25 10:02:14 uos-PC systemd[1]: Failed to start Laptop Mode Tools - Battery Polling Service.
1月 25 10:04:44 uos-PC systemd[1]: Failed to start Laptop Mode Tools - Battery Polling Service.
1月 25 10:07:34 uos-PC systemd[1]: Failed to start Laptop Mode Tools - Battery Polling Service.
1月 25 10:10:07 uos-PC systemd[1]: Failed to start Laptop Mode Tools - Battery Polling Service.
  • systemctl status systemd-modules-load.service
uos@uos-PC:~$ sudo systemctl status systemd-modules-load.service
● systemd-modules-load.service - Load Kernel Modules
   Loaded: loaded (/lib/systemd/system/systemd-modules-load.service; static; vendor preset: enabled)
   Active: failed (Result: exit-code) since Tue 2022-01-25 09:21:56 CST; 49min ago
     Docs: man:systemd-modules-load.service(8)
           man:modules-load.d(5)
  Process: 256 ExecStart=/lib/systemd/systemd-modules-load (code=exited, status=1/FAILURE)
 Main PID: 256 (code=exited, status=1/FAILURE)

Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.
  • journalctl _PID=256 //
uos@uos-PC:~$ sudo journalctl _PID=256
-- Logs begin at Mon 2022-01-24 17:07:35 CST, end at Tue 2022-01-25 10:11:52 CST. --
1月 25 09:21:56 uos-PC systemd-modules-load[256]: Failed to find module 'lightcherry'
1月 25 09:21:56 uos-PC systemd-modules-load[256]: Failed to find module 'lightorange'
1月 25 09:21:56 uos-PC systemd-modules-load[256]: Inserted module 'uos_resources'
uos@uos-PC:~$ Connection to 10.10.53.31 closed by remote host.
  • journalctl _SYSTEMD_UNIT=systemd-modules-load.service //除了使用Process ID进行筛选,还可以直接使用服务名进行筛选。
  • journalctl -xe
    如果不知道这些日志筛选方法,也可以直接用-xe选项来查看,然后肉眼筛选:

1.5.自动加载模块

打开/lib/systemd/system/rc-local.service文件,找到如下内容:
找到:
After=network.target
改为:
After=timers.target

找到:
Type=forking
改为:
Type=simple

在/etc目录增加一个rc.local脚本,在里面写如下内容:

#!/bin/bash
sleep 10
udevadm trigger --type=subsystems --action=add
udevadm trigger --type=devices -S block -S drm -S dri -S tty -S input --action=add
udevadm settle

设置rc.local脚本可执行权限:
sudo chmod 777 /etc/rc.local

refer to

  • https://www.freecodecamp.org/news/the-linux-booting-process-6-steps-described-in-detail/
  • https://www.tecmint.com/linux-boot-process/
  • http://c.biancheng.net/view/1016.html
  • https://www.cnblogs.com/sztom/p/11107485.html

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

杰发科技AC7840——EEPROM初探

0.序 7840和7801的模拟EEPROM使用不太一样 1.现象 按照官方Demo&#xff0c;在这样的配置下&#xff0c;我们看到存储是这样的&#xff08;连续三个数字1 2 3&#xff09;。 使用串口工具的多帧发送功能 看不出多少规律 修改代码后 发现如下规律&#xff1a; 前四个字节是…

VSCode中的注释标签

2023年12月30日&#xff0c;周六上午 在软件开发中&#xff0c;开发者会使用这些标签来提供关于代码功能、版本信息、作者、API使用说明等方面的额外信息。 这些标签的含义通常是&#xff1a; apiNote: 提供有关API使用的注释或说明。author: 标识代码作者的信息。category: …

【 ATU NXP-SBC 系列 】FS26XX GUI_OTP烧录与模拟操作

1. 概述 FS26XX 为了其安全性需求&#xff0c;针对重要暂存器的配置&#xff0c;使用 one time program 的功能&#xff0c;避免不小心修改重要暂存器&#xff0c;导致发生重大意外&#xff0c;使系统丧失功能安全性。FS26XX 也可以让使用者先测试 OTP 后的结果功能&#xff0…

Python:将print内容写入文件

简介&#xff1a;print函数是Python中使用频率非常非常高的函数&#xff0c;其包含四个参数&#xff1a;sep、end、file、flush。 历史攻略&#xff1a; Python基础&#xff1a;输入、输出 Python&#xff1a;将控制台输出保存成文件 参数解析&#xff1a; print()函数可以…

简单了解SQL堆叠注入与二次注入(基于sqllabs演示)

1、堆叠注入 使用分号 ; 成堆的执行sql语句 以sqllabs-less-38为例 ?id1 简单测试发现闭合点为单引号 ?id1 order by 3 ?id1 order by 4使用order by探测发现只有三列&#xff08;字段数&#xff09; 尝试简单的联合注入查询 ?id-1 union select 1,database(),user()-…

爬虫工作量由小到大的思维转变---<第三十五章 Scrapy 的scrapyd+Gerapy 部署爬虫项目>

前言: 项目框架没有问题大家布好了的话,接着我们就开始部署scrapy项目(没搭好架子的话,看我上文爬虫工作量由小到大的思维转变---&#xff1c;第三十四章 Scrapy 的部署scrapydGerapy&#xff1e;-CSDN博客) 正文: 1.创建主机: 首先gerapy的架子,就相当于部署服务器上的;所以…

[mysql 基于C++实现数据库连接池 连接池的使用] 持续更新中

目背景 常见的MySQL、Oracle、SQLServer等数据库都是基于C/S架构设计的&#xff0c;即&#xff08;客户端/服务器&#xff09;架构&#xff0c;也就是说我们对数据库的操作相当于一个客户端&#xff0c;这个客户端使用既定的API把SQL语句通过网络发送给服务器端&#xff0c;MyS…

【Bootstrap学习 day4】

Bootstrap5 列表组 使用Bootstrap创建列表 可以创建三种不类型的HTML列表&#xff1a; 无序列表—顺序无关紧要的项目列表。无序列表中的列表标有项目符号&#xff0c;例如。、等ul>li有序列表—顺序确实很重要的项目列表。有序列表中的列表项用数字标记&#xff0c;例如1、…

欧洲十大跨境电商平台,自养号测评下单的重要性及优势

在欧洲站&#xff0c;用户体量非常庞大&#xff0c;这与近几年人们的消费习惯密不可分&#xff0c;越来越多的人开始网购&#xff0c;据欧盟委员的最新调研显示&#xff0c;在欧盟&#xff0c;近一半(42%)的中小企业通过在线市场销售产品和服务。 所以&#xff0c;逸居海外给大…

Grafana无法发送告警消息的飞书webhook(机器人)

1.问题描述 Grafana无法向飞书机器人发送报警消息&#xff0c;实测使用Grafana自带的webhook也不好使&#xff0c;对于用飞书办公的程序猿非常不便&#xff0c;后来发现一个报警神器&#xff0c;开源免费&#xff0c;关键是好用 PrometheusAlert 2.PrometheusAlert安装 Prom…

ansible_角色的使用

本章主要介绍ansible中角色的使用 了解什么是角色独立地写一个角色使用角色系统自带角色地使用 1.了解角色 正常情况下&#xff0c;配置一个服务如 apache时&#xff0c;要做一系列的操作:安装、拷贝、启动服务等。如果要在不同的机器上重复配置此服务&#xff0c;需要重新执…

企业私有云容器化架构

什么是虚拟化: 虚拟化&#xff08;Virtualization&#xff09;技术最早出现在 20 世纪 60 年代的 IBM 大型机系统&#xff0c;在70年代的 System 370 系列中逐渐流行起来&#xff0c;这些机器通过一种叫虚拟机监控器&#xff08;Virtual Machine Monitor&#xff0c;VMM&#x…

IC入门必备!数字IC中后端设计实现全流程解析(1.3万字长文)

吾爱IC社区自2018年2月份开始在公众号上开始分享数字IC后端设计实现相关基础理论和实战项目经验&#xff0c;累计输出文字超1000万字。全部是小编一个个字敲出来的&#xff0c;绝对没有复制粘贴的情况&#xff0c;此处小编自己得给自己鼓鼓掌鼓励下自己。人生不要给自己设限&am…

【华为数据之道学习笔记】7-5通过感知能力推进企业业务数字化

感知数据在华为信息架构中的位置 感知可以应用于广泛的物理世界和数字世界&#xff0c;感知范围可以从人、物、作业、地点扩展到复杂环境。成熟的用例倾向于以物和人为中心。而在企业中&#xff0c;只有将感知数据纳入整体的数据体系中&#xff0c;才能发挥感知数据的价值。 华…

Java核心技术卷接口的实现与继承多态知识梳理总结

Java核心技术卷接口的实现与继承多态知识梳理总结 接口的概念 在Java程序设计语言中&#xff0c;接口不是类&#xff0c;而是对希望符合这个接口的类的一组需求。 form&#xff1a; Java核心技术卷 I&#xff08;原书第11版&#xff09; 基础知识 by 凯 S.霍斯特曼 在Java中&a…

园林机械部件自动化三维测量检测形位公差-CASAIM自动化三维检测工作站

随着园林机械的广泛应用&#xff0c;对其机械部件的精确测量需求也日益增加。传统的测量方法不仅效率低下&#xff0c;而且精度难以保证&#xff0c;因此&#xff0c;自动化三维测量技术成为了解决这一问题的有效途径。本文将重点介绍CASAIM自动化三维检测工作站在园林机械部件…

线性代数笔记1 12.30

学习视频&#xff1a; 1.4 行列式的计算&#xff08;一&#xff09;_哔哩哔哩_bilibili 以下内容&#xff0c;包含&#xff1a; 二阶三阶行列式 n阶行列式 行列式的性质 行列式按行展开

PiflowX组件-WriteToKafka

WriteToKafka组件 组件说明 将数据写入kafka。 计算引擎 flink 有界性 Streaming Append Mode 组件分组 kafka 端口 Inport&#xff1a;默认端口 outport&#xff1a;默认端口 组件属性 名称展示名称默认值允许值是否必填描述例子kafka_hostKAFKA_HOST“”无是逗号…

9种卷积注意力机制创新方法汇总,含2024最新

今天咱们来聊聊卷积注意力机制。 相信各位在写论文的时候都苦恼过怎么更好地改模型&#xff0c;怎么更高效地提高模型的性能和泛化能力吧&#xff1f;我的建议是&#xff0c;不妨考虑考虑卷积注意力。 卷积注意力机制是一种通过关注输入数据中的不同部分来改进模型性能的方法…

数据结构之树 --- 二叉树

目录 定义二叉树的结构体 二叉树的遍历 递归遍历 非递归遍历 链式二叉树的实现 二叉树的功能接口 先序遍历创建二叉树 后序遍历销毁二叉树 先序遍历查找树中值为x的节点 层序遍历 上篇我们对二叉树的顺序存储堆进行了讲述&#xff0c;本文我们来看链式二叉树。 定…