Linux内核开发之编译和运行
在本篇文章中,读者可以跟着我们的一步一步的教程最终学会如何搭建Linux内核开发环境,并最终能成功运行自己编译的内核,本文主要是针对arm架构来编译Linux内核,因此读者不仅可以学习到如果编译内核,还将学会如何使用QEMU搭建arm仿真环境。 本文将介绍两种Linux内核编译方法
- 第一种为不借助任何编译系统的原始编译方法,相对较为复杂
- 第二种则借助BuildRoot编译系统实现了一键编译,相对比较简单
编译Linux内核需要在Linux系统中运行,推荐使用Ubuntu,并安装 build-essentials 包,本
1. 原始编译
如果不使用编译系统进行一键式Linux编译的话,我们需要先获取交叉编译器,有几种不同的方式:
- 直接在系统中安装
- 使用crosstool-ng
- 使用第二章中使用 buildroot
编译出来的
host
工具链
本文第二章将介绍buildroot的使用方法,因此我们的环境中已经有buildroot帮我们生成的交叉编译器,因此我们会使用第三种方式,将buildroot编译出来的工具添加到PATH
里边
|
|
1.1 U-Boot配置和编译
下载U-Boot源码https://github.com/u-boot/u-boot 以后,我们需要拷贝默认配置
|
|
如果我们需要修改默认配置可以运行
|
|
保存修改以后的配置,然后运行make -j32
启动编译,编译的结果会放置在u-boot文件夹的根目录,我们使用QEMU测试下刚刚编译好的U-Boot,运行
|
|
以后将成功启动u-boot,在QEMU可以按 ctrl-a, x退出
1.1.1 向SD卡中安装U-Boot
- 创建空的SD卡文件
dd if=/dev/zero of=sd.img bs=1M count=1024
- 使用cfdisk在SD卡中创建分区
cfdisk sd.img
, 并格式化
|
|
- 带着SD卡启动QEMU
|
|
1.1.2 配置QEMU网络接口,并启动U-Boot
-
创建
qemu-myifup
文件1 2 3
#!/bin/sh /sbin/ip a add 192.168.0.1/24 dev $1 /sbin/ip link set $1 up
-
更改文件模式
chmod +x qemu-myifup
-
启动QEMU
1 2 3 4
sudo qemu-system-arm -M vexpress-a9 -m 128M -nographic \ -kernel u-boot-2020.04/u-boot \ -sd sd.img \ -net tap,script=./qemu-myifup -net nic
-
在U-Boot中配置IP
1 2 3
setenv ipaddr 192.168.0.100 setenv serverip 192.168.0.1 saveenv
-
在U-Boot中ping主机
1
ping 192.168.0.1
-
在主机中安装tftp服务器(/srv/tftp),则可以实现,在U-Boot中使用tftp从主机下载文件到QEMU
1.2 Linux编译
- 设置交叉编译器
export CROSS_COMPILE=arm-linux-
- 下载linux源码,并使用默认配置
make ARCH=arm vexpress_defconfig
(可以运行make ARCH=arm help | grep defconfig
来搜索配置)
|
|
- 运行
make -j32
编译结束以后,文件的位置:
- 镜像:
arch/arm/boot/zImage
- Device Tree:
arch/arm/boot/dts/vexpress-v2p-ca9.dtb
1.3 U-Boot加载Linux
- 在U-Boot中设置Linux启动参数
|
|
- 使用tftp加载经常和DTB文件
|
|
- 启动Kernel
|
|
在这里启动肯定会抛出panic,因为我们没有提供root filesystem
也可以通过设置bootcmd来自动化前边的操作
|
|
2. 使用编译系统 Buildroot
2.1 使用Buildroot来编译Linux
Buildroot is a tool that simplifies and automates the process of building a complete Linux system for an embedded system, using cross-compilation. In order to achieve this, Buildroot is able to generate a cross-compilation toolchain, a root filesystem, a Linux kernel image and a bootloader for your target. Buildroot can be used for any combination of these options, independently (you can for example use an existing cross-compilation toolchain, and build only your root filesystem with Buildroot).
使用BuildRoot可以大大简化Linux内核的编译过程,实现一键编译,在开始编译以前,我们需要到 BuildRoot官方网页 下载BuildRoot编译系统,下载完毕后,我们将压缩包解压以后就可以开始配置我们要编译的Linux内核了
- 运行
make menuconfig
可以从头开始配置Linux - 也可以使用默认的一些配置,通过运行
make list-defconfigs
来列出所有支持的默认配置,然后通过make <defconfig-name>
来使用某个默认配置(在这里我们选择arm)配置会生成到.config
文件夹中
配置完成以后通过运行make命令来启动编译
- 运行
make -j32
来启动多线程编译
当成功编译以后,编译结果将被存放在 output
目录中其中
host
目录包含在 host
机器(也就是我们用户编译Linux内核的机器)上用到的工具,例如
- 交叉编译器名称,例如:
arm-buildroot-linux-uclibcgnueabi
- 交叉编译器可执行文件,在目录
output/host/bin
- Sysroot:
output/host/arm-buildroot-linux-uclibcgnueabi/sysroot
images
目录包含目标板上用到的文件,例如
- Root file system:
rootfs.ext2
- Device tree:
versatile-pb.dtb
- Kernel:
zImage
2.2 在QEMU上运行Linux
在这里我们使用 Direct Linux Boot
的方法在QEMU中启动Linux内核,大家可以在QEMU官网介绍
中找到Direct Linux Boot的相关介绍,简单来说就是QEMU支持的不使用启动镜像的方式来加载内核镜像。
因为我们在编译内核前选择了arm架构,因此我们编译出来的Linux内核需要在arm环境中才能运行,QEMU提供了针对arm的仿真,我们在安装好QEMU的系统中使用qemu-system-arm
命令来仿真arm架构
通过运行下述命令来启动我们刚刚编译好的内核
|
|

2.3 为我们自己的Linux写一个hello world
代码和编译
在host机器上创建一个hello.c文件
|
|
使用 output/host/bin目录中的交叉编译编译hello.c
|
|
使用file命令可以检查文件格式,确认文件为arm架构的ELF格式
|
|
可执行文件导入到QEMU系统
将 images 里的rootfs 挂在的host机器上
|
|
将编译出来的hello可执行文件拷贝到rootfs
|
|
取消挂载
|
|
启动QEMU并运行hello文件
通过Direct Linux Boot启动QEMU,在系统启动后,可以在/root
目录下找到hello
可执行文件,运行后将输出我们打印的字符串
|
|
类似文章

智能家居好伙伴 树莓派,MQTT和Python – 下篇
在本篇文章中,我们主要结合代码来讲解,如何在树莓派上使用Python开发基于MQTT的通讯机制, 项目的整体设计请阅读智能家居好伙伴 树莓派,MQTT和Python – 上篇 本文中提到的代码均在GitHub上共享,大家可以在文章结尾找到GitHub仓库地址。
阅读更多
智能家居好伙伴 树莓派,MQTT和Python – 上篇
作为一个技术宅,不在业余时间折腾折腾,总觉得浑身不得劲,能够利用自己的知识,使自己的生活更加舒适便捷,这也会带来极大的满足感,智能家居项目就是这样一种项目,通过自己的奇思妙想,搭建符合自己和家人生活习惯的贴近生活的小设备是非常有意思的一件事情。 而在搭建这样系统的过程中,我们也可以从中学到更多的技术知识,增加自己的技术储备。在这篇文章中,我们将以树莓派为载体,使用Python搭建一个最基础的智能家居设备(温湿度传感器 + 电脑远程唤醒),目的是通过手机APP能够观察到室内温度湿度,并且可以通过APP远程唤醒自己的NAS服务器。
阅读更多
一文掌握Pandas数据结构
在网络上的Pandas教程中,很多都提到了如何使用Pandas将已有的数据(如csv,如hdfs等)直接加载成Pandas数据对象,然后在其基础上进行数据分析操作,但是,很多时候,我们需要自己创建Pandas数据对象,并填入一些数据,常见的应用场景如:我们想要将现有的数据进行处理,并生成一个新的Pandas数据对象,还有,我们想利用Pandas的数据保存功能(比如to_csv, to_json, to_hdf等等)把我们采集到的数据写入到IO里边,因此掌握Pandas对象的特性,以及如何创建也是很重要的。因此在本篇文章中,我们主要侧重于介绍Pandas数据结构本身的特性,以及如何创建一个Series或者DataFrame数据对象,并填入一些数据。
阅读更多