笔记 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)

谢谢

相关推荐
幼儿园蛋小黑31 分钟前
ARM 中断机制详解
arm
晊晌_h20 小时前
IMX6ULL裸机开发:定时器(GPT/EPIT)与UART串口
arm·定时器·arm裸机开发
幼儿园蛋小黑6 天前
ARM 时钟与定时器详解:从原理到实践
arm
幼儿园蛋小黄6 天前
从定时器到时钟:ARM 嵌入式学习总结
arm
祖力556 天前
ARM时钟
嵌入式硬件·arm·时钟·imx6ull
koi77u6 天前
嵌入式学习——ARM(3)
arm
学linux的QQ蛋7 天前
i.MX6ULL GIC 中断整体知识点总结和ARM时钟重点总结
arm·时钟·中断
G.E.M.小白7 天前
【IMX6ULL ARM内核启动与时钟系统超详解】PLL/PFD/分频/根时钟配置
嵌入式·arm·时钟·imx6ull
koi77u7 天前
嵌入式学习——ARM(1)
arm
myy-learn7 天前
ARM-点亮第一颗LED
arm