笔记 25 - 2 :linux 驱动模块移植,创建自定义驱动(编译为模块),调整 shell 里字体大小,

(298 - a)

++

++ 接着解释下这个 makefile 文件 :

++

(298 - b)解释 makefile 的二次编译:

++

(298 - c) 开始执行 make ,编译,以及运行 :

++

++ USB 挂载,跟 NFS 一样,老师教了又一种方式 :

++

(299)以下是一些注释 :

(230)

(231)

c 复制代码
// 头文件
#include <linux/fs.h>
#include <linux/cdev.h>

#define LED_MAJOR 500   // 和 mknod 的 500 一致
#define LED_MINOR 0

// 设备操作集:open/read/write/release
static struct file_operations led_fops = {
    .owner = THIS_MODULE,
    .open  = led_open,
    .write = led_write,
};

static int __init led_drv_init(void)
{
    // 注册字符设备,主号500,名字"led",绑定fops
    int ret = register_chrdev(LED_MAJOR, "led", &led_fops);
    if(ret < 0){
        pr_err("register_chrdev fail\n");
        return ret;
    }
    pr_info("led drv register ok, major=%d\n", LED_MAJOR);
    return 0;
}

static void __exit led_drv_exit(void)
{
    unregister_chrdev(LED_MAJOR, "led");
}

module_init(led_drv_init);
module_exit(led_drv_exit);
MODULE_LICENSE("GPL");
c 复制代码
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/module.h>

static int major;
static struct cdev led_cdev;
static struct class *led_class;
static struct device *led_dev;

static struct file_operations led_fops = {
    .owner = THIS_MODULE,
    .open  = led_open,
    .write = led_write,
};

static int __init led_drv_init(void)
{
    dev_t devno;
    // 1. 动态申请主次设备号(不用自己硬写500)
    int ret = alloc_chrdev_region(&devno, 0, 1, "led_auto");
    if(ret) return ret;

    major = MAJOR(devno);
    // 2. 初始化cdev,绑定操作函数集
    cdev_init(&led_cdev, &led_fops);
    led_cdev.owner = THIS_MODULE;
    cdev_add(&led_cdev, devno, 1);

    // 3. 创建设备类 /sys/class/led
    led_class = class_create(THIS_MODULE, "led");
    if(IS_ERR(led_class)){
        ret = PTR_ERR(led_class);
        goto err_cdev;
    }
    // 4. 自动生成 /dev/led 节点!【重点】
    led_dev = device_create(led_class, NULL, devno, NULL, "led");
    if(IS_ERR(led_dev)){
        ret = PTR_ERR(led_dev);
        goto err_class;
    }
    pr_info("auto create /dev/led, major=%d minor=%d\n", major, MINOR(devno));
    return 0;

err_class:
    class_destroy(led_class);
err_cdev:
    cdev_del(&led_cdev);
    unregister_chrdev_region(devno,1);
    return ret;
}

static void __exit led_drv_exit(void)
{
    dev_t devno = MKDEV(major, 0);
    device_destroy(led_class, devno);
    class_destroy(led_class);
    cdev_del(&led_cdev);
    unregister_chrdev_region(devno,1);
}

module_init(led_drv_init);
module_exit(led_drv_exit);
MODULE_LICENSE("GPL");

++ 四、用户态测试代码极简示例(配套上面驱动) :

c 复制代码
// test_led.c
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main(void)
{
    int fd = open("/dev/led", O_WRONLY);
    if(fd < 0){
        perror("open /dev/led");
        return -1;
    }
    write(fd, "1", 1); // 传给驱动write,点亮LED
    close(fd);
    return 0;
}

五、实操命令汇总 :

bash 复制代码
# 加载驱动
insmod led.ko
# 查看字符设备
cat /proc/devices
# 看/dev/led信息
ls -l /dev/led
# 卸载
rmmod led

(232)devtmpfs 在内核态;udev 是用户态守护进程 :

(233)

(234)

(235)

谢谢

相关推荐
奔跑的架构师1 天前
[A-51]ARMv9/v8-SCMI系统架构
linux·arm开发·架构·系统架构·arm
susplus1 天前
【Linux驱动开发】中断、工作队列及中断子系统详解
arm·中断·linux驱动开发·中断子系统
chu_bingzhi2 天前
ARMv8体系结构
arm
一直C4 天前
嵌入式 Linux 驱动开发学习笔记(三)设备树、GPIO子系统、中断与外设驱动实战
驱动开发·单片机·嵌入式硬件·嵌入式·arm·imx6ull
zbyyd5 天前
Linux字符设备驱动:LED驱动实战开发
linux·单片机·arm·驱动
祖力556 天前
驱动工程搭建与字符设备驱动框架
linux·运维·服务器·内核·arm·imx6ull·驱动
susplus6 天前
【Linux驱动开发】字符设备介绍 | LED灯驱动基本实现(自动申请设备号+手动添加节点)
arm·led驱动·linux驱动开发
gscsded7 天前
MCUboot裸机移植实战
单片机·嵌入式硬件·arm
想喝奶茶啾啾7 天前
AMBA CHI架构以及规范中使用的术语 翻译笔记(1)
笔记·arm·chi
susplus8 天前
【IMX6ULL Linux系统移植】内核编译裁剪 + rootfs 构建 + 完整启动流程梳理
linux内核·arm·rootfs·linux启动