嵌入式 Linux 开发全攻略:内核、驱动与编译技巧

2026年8月19日 0 By admin

嵌入式 Linux 开发全攻略

内核与驱动开发

嵌入式 Linux 开发中,内核和驱动是核心组成部分。内核负责硬件抽象和系统资源管理,驱动则负责与硬件设备通信。

内核编译

# 创建交叉编译工具链
mkdir build
cd build
../configure --host=arm-linux-gnueabi
make

# 编译内核
make menuconfig
make
make modules
make modules_install
make install

驱动开发

驱动开发通常涉及编写设备驱动程序,以下是一个简单的字符设备驱动示例:

#include 
#include 
#include 

static int major;
static struct class *cls = NULL;
static struct cdev cdev;

static int device_open(struct inode *inode, struct file *file) {
    printk(KERN_INFO "Device opened\n");
    return 0;
}

static int device_release(struct inode *inode, struct file *file) {
    printk(KERN_INFO "Device released\n");
    return 0;
}

static long device_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {
    printk(KERN_INFO "Device ioctl called\n");
    return 0;
}

static struct file_operations fops = {
    .open = device_open,
    .release = device_release,
    .unlocked_ioctl = device_ioctl,
};

static int __init device_init(void) {
    printk(KERN_INFO "Loading device driver\n");
    major = register_chrdev(0, "mydevice", &fops);
    if (major < 0) {
        printk(KERN_ALERT "Failed to register major number\n");
        return major;
    }
    cls = class_create(THIS_MODULE, "mydevice");
    if (IS_ERR(cls)) {
        unregister_chrdev(major, "mydevice");
        printk(KERN_ALERT "Failed to register class\n");
        return PTR_ERR(cls);
    }
    device_create(cls, NULL, MKDEV(major, 0), NULL, "mydevice");
    cdev_init(&cdev, &fops);
    if (cdev_add(&cdev, MKDEV(major, 0), 1) < 0) {
        printk(KERN_ALERT "Failed to add cdev\n");
        class_destroy(cls);
        unregister_chrdev(major, "mydevice");
        return -1;
    }
    return 0;
}

static void __exit device_exit(void) {
    printk(KERN_INFO "Unloading device driver\n");
    cdev_del(&cdev);
    class_destroy(cls);
    unregister_chrdev(major, "mydevice");
}

module_init(device_init);
module_exit(device_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple character device driver");

设备树

设备树(Device Tree)是描述硬件配置信息的文件,它提供了硬件与软件之间的接口。

创建设备树

# 创建设备树文件
dtc -I dts -O dtb -o mydevice.dtb mydevice.dts

Buildroot/Yocto/交叉编译

交叉编译是嵌入式开发中的常见需求,以下是在 Buildroot 和 Yocto 中进行交叉编译的示例。

Buildroot

# 在 Buildroot 中创建交叉编译工具链
make menuconfig
make toolchain
make

Yocto

# 在 Yocto 中创建交叉编译工具链
source oe-init-buildenv
bitbake core-image-minimal

U-Boot

U-Boot 是嵌入式系统中的引导加载程序,负责启动内核和初始化硬件。

编译 U-Boot

# 编译 U-Boot
make CROSS_COMPILE=arm-linux-gnueabi- all

字符设备

字符设备是 Linux 系统中的一种设备类型,以下是一个简单的字符设备示例。

#include 
#include 
#include 

static int major;
static struct class *cls = NULL;
static struct cdev cdev;

static int device_open(struct inode *inode, struct file *file) {
    printk(KERN_INFO "Device opened\n");
    return 0;
}

static int device_release(struct inode *inode, struct file *file) {
    printk(KERN_INFO "Device released\n");
    return 0;
}

static long device_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {
    printk(KERN_INFO "Device ioctl called\n");
    return 0;
}

static struct file_operations fops = {
    .open = device_open,
    .release = device_release,
    .unlocked_ioctl = device_ioctl,
};

static int __init device_init(void) {
    printk(KERN_INFO "Loading device driver\n");
    major = register_chrdev(0, "mydevice", &fops);
    if (major < 0) {
        printk(KERN_ALERT "Failed to register major number\n");
        return major;
    }
    cls = class_create(THIS_MODULE, "mydevice");
    if (IS_ERR(cls)) {
        unregister_chrdev(major, "mydevice");
        printk(KERN_ALERT "Failed to register class\n");
        return PTR_ERR(cls);
    }
    device_create(cls, NULL, MKDEV(major, 0), NULL, "mydevice");
    cdev_init(&cdev, &fops);
    if (cdev_add(&cdev, MKDEV(major, 0), 1) < 0) {
        printk(KERN_ALERT "Failed to add cdev\n");
        class_destroy(cls);
        unregister_chrdev(major, "mydevice");
        return -1;
    }
    return 0;
}

static void __exit device_exit(void) {
    printk(KERN_INFO "Unloading device driver\n");
    cdev_del(&cdev);
    class_destroy(cls);
    unregister_chrdev(major, "mydevice");
}

module_init(device_init);
module_exit(device_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple character device driver");

调试

调试是嵌入式开发中不可或缺的环节,以下是一些常用的调试方法。

GDB 调试

# 使用 GDB 调试内核
gdb vmlinux
target remote localhost:1234

printk 调试

printk(KERN_INFO "This is a debug message\n");

启动优化

优化启动过程可以提高系统性能和响应速度。

优化内核配置

make menuconfig

优化引导加载程序

make CROSS_COMPILE=arm-linux-gnueabi- all

以上是嵌入式 Linux 开发的全攻略,希望对您有所帮助。