编写 Linux 驱动(通常指内核模块驱动)一般包括:准备环境 → 编写驱动代码 → 编写 Makefile → 编译 → 加载/测试 → 调试。下面我按新手可操作流程给你讲,并附带一个最简字符设备驱动示例。
sudo apt update
sudo apt install build-essential linux-headers-$(uname -r)
uname -r
驱动必须和当前运行内核版本一致。
| 类型 | 说明 |
|---|---|
| 字符设备 | 最常见(如 LED、按键、串口) |
| 块设备 | 硬盘、SD 卡 |
| 网络设备 | 网卡 |
| 平台设备 | SoC 上的设备(ARM 常见) |
新手建议从 字符设备驱动 学起。
hello_drv.c#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/init.h>
#include <linux/cdev.h>
static int major;
static char buf[100];
static int hello_open(struct inode *inode, struct file *file)
{
printk("hello open\n");
return 0;
}
static ssize_t hello_read(struct file *file, char __user *ubuf, size_t size, loff_t *off)
{
copy_to_user(ubuf, buf, size);
return size;
}
static ssize_t hello_write(struct file *file, const char __user *ubuf, size_t size, loff_t *off)
{
copy_from_user(buf, ubuf, size);
printk("write: %s\n", buf);
return size;
}
static struct file_operations hello_fops = {
.owner = THIS_MODULE,
.open = hello_open,
.read = hello_read,
.write = hello_write,
};
static int __init hello_init(void)
{
major = register_chrdev(0, "hello_drv", &hello_fops);
printk("hello driver init, major=%d\n", major);
return 0;
}
static void __exit hello_exit(void)
{
unregister_chrdev(major, "hello_drv");
printk("hello driver exit\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
obj-m += hello_drv.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
make
生成:
hello_drv.ko
sudo insmod hello_drv.ko
dmesg | tail
ls /proc/devices
sudo mknod /dev/hello c 主设备号 0
echo "hello" > /dev/hello
cat /dev/hello
sudo rmmod hello_drv
dmesg:查看 printk 输出printk 日志级别:printk(KERN_INFO "info\n");
cat /proc/kmsgfile_operations 详解platform_driver / device_treerequest_irq)ioctlsysfs / procdrivers/Documentation/如果你愿意,可以告诉我:
我可以给你针对具体硬件的驱动示例。