删除之前编译生成的文件和配置文件
make mrproper
生成.config文件
make menuconfig
编译
make -j4
1. No rule to make target ‘debian/canonical-certs.pem‘, needed by ‘certs/x509_certificate_list‘
vim .config
修改CONFIG_SYSTEM_TRUSTED_KEYS为""
修改CONFIG_SYSTEM_REVOCATION_KEYS为""
2.BTF: .tmp_vmlinux.btf: pahole (pahole) is not available Failed to generate BTF for vmlinux
sudo apt install linux-tools-common
编辑.config文件,将CONFIG_DEBUG_INFO_BTF设置为n
后续
root@100ask:/home/book/Downloads/linux-5.19/arch/x86/boot# file bzImage
bzImage: Linux kernel x86 boot executable bzImage, version 5.19.0 (root@100ask) #2 SMP PREEMPT_DYNAMIC Wed Aug 2 09:35:26 EDT 2023, RO-rootFS, swap_dev 0xA, Normal VGA
- 编译busybox
make menuconfig
勾选 Build static binary 生成静态链接的busybox二进制文件再make -j4进行编译
- 安装
make install
会安装在当前busybox目录的_install目录下
- 制作initramfs.img
写如下Makefile文件:initramfs:cd ./initramfs_dir && find . -print0 | cpio -ov --null --format=newc | gzip -9 > ../initramfs.imgrun:qemu-system-x86_64 \-kernel bzImage \-initrd initramfs.img \-m 512M \-nographic \-append "earlyprintk=serial,ttyS0 console=ttyS0"
在启动Linux时,会执行以下步骤:
1.引导加载器加载内核映像(这里是bzImage)
2.内核加载并挂载根文件系统启动init进程
3.init进程使用根文件系统下的/init脚本来继续启动系统
root@100ask:/home/book/linux-demo#下
执行make initramfs即可生成根文件系统的映像文件initramfs.img
执行make run就会启动qemu虚拟机
-
/init脚本
#!/bin/busybox sh/bin/busybox mkdir -p /proc && /bin/busybox mount -t proc none /proc /bin/busybox echo "Hello"/bin/busybox sh
-
文件结构
├── bzImage
├── initramfs_dir
│ ├── bin
│ │ └── busybox
│ └── init
├── initramfs.img
└── Makefile -
使用
root@100ask:/home/book/Downloads/busybox-1.36.1/_install/bin# busybox echo 123 123
-
退出:ctrl+a,then press x
-
将内核中的proc文件系统挂载到/proc文件夹,这样就可以通过访问/proc下的文件和目录,获取到与内核和系统相关的信息
-
显示进程
init中加入下面这行:/bin/busybox mkdir -p /proc && /bin/busybox mount -t proc none /proc
这样执行busybox ps就可以显示进程了
-
修改shell提示符
加一行 export $PS1='(kernel) =>'
文件系统
文件系统常用格式:ext2、yaffs2
内存文件系统:ramdisk:用内存模拟块设备,并格式化为文件系统格式ramfs:利用linux会把块设备的数据缓存到内存中的机制实现,不会将数据写回到存储设备tmpfs:tmpfs是ramfs的衍生物,有容量大小限制、允许向交换空间(swap) 写入数据
内核早期启动的临时根文件系统:initramfs:
linux最终使用的完整的文件系统:rootfs:是ramfs和tmpfs的一个实现,包含系统所有基本文件和目录,是完整的Linux文件系统
内核在启动初始化过程中会解压缩initrd文件,然后将解压后的initrd挂载为根目录,然后执行根目录中的/init脚本,您就可以在这个脚本中运行initrd文件系统中的内核模块自动加载机制udevd,让它来自动加载realfs(真实文件系统)存放设备的驱动程序,以及在/dev目录下建立必要的设备节点。在udevd自动加载磁盘驱动程序之后,就可以mount真正的根目录,并切换到这个根目录中来。
详细描述
initfd和initramfs
- initrd:有image格式和cpio格式。基于ramdisk的小型根目录,包含启动阶段中需要的文件和脚本,会在系统启动时被读入到内存,执行其中的/init脚本。
为了精简内核代码,将加载各种设备驱动和模块的代码写在init脚本中,放在大小固定大小的块设备上,放在用户态来做。
由于其基于块设备,因此需要内核有文件系统驱动 - initramfs:本质上是cpio格式的initrd
initramfs是initrd的继承者,都用来做一些内核不容易做的事情,比如挂载文件系统、加载模块等
怎样在linux中添加一个系统调用
下面以获得cpu个数为例:
- 在arch/x86/entry/syscalls/syscall_64.tbl中注册系统调用号
451 common get_cpu_number sys_get_cpu_number
- 在include/linux/syscalls.h中声明系统调用函数
asmlinkage long sys_get_cpu_number(void);
- 在kernel/sys.c中实现系统调用函数
SYSCALL_DEFINE0(get_cpu_number) {return num_present_cpus(); }
- 然后重新编译linux内核(使用默认配置即可)
- 测试程序get_cpu.c:
结构和之前的linux-demo类似,只是bzImage是重新编译内核生成的#include <sys/syscall.h>int main() {int cpu_numbers= syscall(451);return 0; }
├── get_cpu.c 测试程序
├── bzImage 编译内核生成的镜像
├── initramfs_dir 目录
│ ├── bin 目录
│ │ └── busybox 编译busybox生成的可执行文件
│ └── get_cpu 可执行文件
│ └── init 脚本文件
├── initramfs.img 执行Makefile下的make initramfs会生成该镜像文件
└── Makefile 也和linux-demo中写的一样
执行gcc -static get_cpu.c -o get_cpu生成静态可执行文件,所有的依赖库都会被静态链接到可执行文件中,从而使可执行文件在其他系统上运行时不需要依赖动态库
qemu的按键驱动程序
-
编译内核
我的linux内核目录为~/100ask_imx6ull-qemu/linux-4.9.88-
设置环境变量
export ARCH=arm export CROSS_COMPILE=arm-linux-gnueabihf-
-
生成.config文件 make menuconfig
为避免后期报错:button_drv: version magic '4.9.88-g8f6c88de SMP mod_unload modversions ARMv7 p2v8 ’ should be '4.9.88-g8f6c88de SMP preempt mod_unload modversions ARMv7 p2v8 ',要做如下设置
编译内核时使用抢占式模型,需要设置Kernel Features -> Preemption Model为Preemptible Kernel (Low-Latency Desktop)
-
make -j4
-
修改内核源码的version magic
为避免加载的驱动所使用的内核版本和系统运行的版本不一致,导致后期报错:Unknown symbol __gnu_mcount_nc
打开内核include/generated/utsrelease.h文件,修改version magic为开发板的版本。
#define UTS_RELEASE "4.9.88-g8f6c88de"
-
-
编译按键驱动程序
-
在Makefile中指定内核路径KERN_DIR
KERN_DIR = /home/book/100ask_imx6ull-qemu/linux-4.9.88 all:make -C $(KERN_DIR) M=`pwd` modules$(CROSS_COMPILE)gcc -o button_test button_test.c clean:make -C $(KERN_DIR) M=`pwd` modules cleanrm -rf modules.orderrm -f ledtest obj-m += button_drv.o obj-m += board_100ask_imx6ull-qemu.o
-
make编译,然后将ko文件和程序复制到nfs文件夹
cp *.ko button_test /home/book/nfs_rootfs/
-
-
启动qemu,挂载nfs
mount -t nfs -o nolock,vers=3 10.0.2.2:/home/book/nfs_rootfs /mnt
-
安装模块
insmod button_drv.ko
insmod board_100ask_imx6ull-qemu.ko
-
查看内核日志
dmesg | grep hello