Yocto · Bài 8/9

Bài 8: Thêm helloworld kernel module trong Yocto bằng devtool

1 lượt đọc4 phút đọc

Sau khi biết dùng devtool để sửa recipe, bước tiếp theo rất tự nhiên là dùng nó để sửa chính kernel. Bài này hướng dẫn thêm một kernel module helloworld vào kernel của Yocto nhánh scarthgap, build, chạy trên QEMU và lưu thay đổi thành một bản vá nằm trong layer riêng.

1.Tạo layer chứa thay đổi kernel

Trước hết, thiết lập môi trường:

bash
cd ~/yocto/poky
source oe-init-build-env

Tạo một layer mới tên meta-kernelmodule và thêm vào dự án:

bash
bitbake-layers create-layer ../meta-kernelmodule
bitbake-layers add-layer ../meta-kernelmodule
bitbake-layers show-layers

Lệnh add-layer tự cập nhật conf/bblayers.conf, bạn không cần sửa tay.

2.Lấy mã nguồn kernel bằng devtool modify

bash
devtool modify virtual/kernel

virtual/kernel là tên chung chỉ recipe kernel đang dùng, được xác định bởi biến PREFERRED_PROVIDER_virtual/kernel. Kiểm tra bằng:

bash
bitbake -e core-image-minimal | grep ^PREFERRED_PROVIDER_virtual/kernel=

Với cấu hình mặc định, kết quả là linux-yocto. Sau khi chạy devtool modify, mã nguồn kernel được đặt tại:

bash
build/workspace/sources/linux-yocto/

Đây là một kho git đầy đủ, bạn thấy các thư mục quen thuộc như arch, drivers, fs, kernel... Việc tải về có thể mất vài phút.

3.Viết kernel module helloworld

3.1. Tạo thư mục module

Đặt module trong thư mục drivers/:

bash
cd ~/yocto/poky/build/workspace/sources/linux-yocto
mkdir drivers/helloworld

3.2. Tệp mã nguồn helloworld.c

c
#include <linux/module.h>
#include <linux/init.h>

#define DRIVER_AUTHOR "helloworld <your@email>"
#define DRIVER_DESC   "Hello world kernel module in yocto"
#define DRIVER_VERS   "1.0"

static int __init hello_world_init(void)
{
    printk(KERN_INFO "Hello world kernel module in yocto\n");
    return 0;
}

static void __exit hello_world_exit(void)
{
    printk(KERN_INFO "Goodbye helloworld kernel module in yocto\n");
}

module_init(hello_world_init);
module_exit(hello_world_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_VERSION(DRIVER_VERS);

Hàm hello_world_init chạy khi module được nạp, còn hello_world_exit chạy khi gỡ module.

3.3. Tệp Kconfig

Tạo drivers/helloworld/Kconfig:

bash
config HELLOWORLD
	tristate "Hello World Kernel Module"
	default y
	help
	  A simple Hello World kernel module.

Với tristate, module có thể được biên dịch cứng vào kernel (y), biên dịch riêng (m) hoặc bỏ qua (n). Dòng default y chọn biên dịch cứng, nên thông điệp sẽ xuất hiện ngay khi kernel khởi động.

3.4. Tệp Makefile

Tạo drivers/helloworld/Makefile:

bash
obj-$(CONFIG_HELLOWORLD) += helloworld.o

4.Nối module vào hệ thống build của kernel

Kernel chỉ biết đến module của bạn khi các tệp ở thư mục cha trỏ tới nó. Sửa hai tệp trong drivers/.

Thêm vào cuối drivers/Kconfig, ngay trước dòng endmenu cuối cùng:

bash
source "drivers/helloworld/Kconfig"

Thêm vào drivers/Makefile:

bash
obj-y += helloworld/

5.Build và kiểm tra

Build kernel bằng devtool, rồi build image:

bash
devtool build linux-yocto
bitbake core-image-minimal

Chạy thử trên QEMU:

bash
runqemu qemux86-64 core-image-minimal nographic

Đăng nhập root, rồi tìm thông điệp của module trong nhật ký kernel:

bash
root@qemux86-64:~# dmesg | grep Hello
[    4.308025] Hello world kernel module in yocto

Thấy dòng đó nghĩa là module đã chạy ngay khi kernel khởi động. Con số thời gian ở đầu dòng có thể khác trên máy của bạn.

6.Lưu thay đổi bằng devtool finish

Khi đã hài lòng, bạn muốn giữ lại thay đổi trong layer riêng thay vì để nó nằm trong workspace tạm.

6.1. Commit thay đổi trong kho kernel

bash
cd ~/yocto/poky/build/workspace/sources/linux-yocto
git status
git add .
git commit -m "Learn Yocto: add helloworld kernel module"

Lệnh git status sẽ cho thấy hai tệp đã sửa (drivers/Kconfig, drivers/Makefile) và thư mục mới drivers/helloworld/.

6.2. Chạy devtool finish

bash
devtool finish linux-yocto ~/yocto/poky/meta-kernelmodule

Devtool biến commit của bạn thành một bản vá và tạo tệp bbappend trong layer:

bash
meta-kernelmodule/
└── recipes-kernel
    └── linux
        ├── linux-yocto
        │   └── 0001-Learn-Yocto-add-helloworld-kernel-module.patch
        └── linux-yocto_%.bbappend

Từ giờ, bất kỳ ai dùng layer meta-kernelmodule đều có kernel kèm module helloworld, mà không cần đụng vào mã gốc của Yocto. Thư mục mã nguồn trong workspace vẫn còn, bạn có thể xóa tay nếu không cần nữa.

7.Kết luận

Bạn đã thêm một kernel module vào kernel của Yocto bằng devtool: lấy mã, viết module, nối vào hệ thống build, thử trên QEMU và lưu lại dưới dạng bản vá trong layer riêng. Cách làm này giữ cho thay đổi gọn, dễ theo dõi và dễ nâng cấp kernel về sau.