当前位置: 首页 > news >正文

Linux内核编译流程

删除之前编译生成的文件和配置文件

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:
    #include <sys/syscall.h>int main()
    {int cpu_numbers= syscall(451);return 0;
    }
    
    结构和之前的linux-demo类似,只是bzImage是重新编译内核生成的
    ├── 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

http://www.lryc.cn/news/383139.html

相关文章:

  • 昇思25天学习打卡营第2天 | 张量Tensor
  • 时间安排 |规划
  • PS系统教程28
  • 如何在web页面下做自动化测试?
  • spring源码环境的搭建
  • 小山菌_代码随想录算法训练营第三十四天| 56. 合并区间、
  • 让工厂像手机一样更“聪明”
  • vue2与vue3数据响应式对比之检测变化
  • Spring Cloud - 开发环境搭建
  • 绘制图形
  • SpringAop实战(xml文件/纯注解两种方式)
  • (八)Linux的进程与线程
  • Map-JAVA面试常问
  • prometheus+grafana搭建监控系统
  • flink学习-flink sql
  • 高考填报志愿攻略,5个步骤选专业和院校
  • Kubernetes排错(十)-处理容器数据磁盘被写满
  • 使用QtGui显示QImage的几种方法
  • C++ lamda
  • Linux_应用篇(27) CMake 入门与进阶
  • 51单片机STC89C52RC——8.1 8*8 LED点阵模块(点亮一个LED)
  • 2024最新免费版轻量级Navicat Premium Lite 下载和安装教程
  • PHP+laravel 生成word
  • redis集群简单介绍及其搭建过程
  • linux桌面运维----第五天
  • 【SQL Server数据库】简单查询
  • Docker 从入门到精通(大全)
  • 基于JSP的在线教育资源管理系统
  • 在java中代理http请求,如何避免陷入循环?
  • 国内镜像源网址