Linux驱动学习之点灯(四,linux2.6)

上篇最后的第二种点灯方法年代比较久远,register_chrdev()这个函数一下申请了255个设备号,不建议使用 如下图

下图的函数在linux2.6里是上图函数的升级版,不过他是静态分配,后续还得添加到cdev里

从上图函数不难发现,静态申请多个设备号,主设备号不变,次设备号++
一般我们会使用下图函数动态申请设备号,并添加到cdev里

第一个参数:无符号32位设备号的地址,申请成功后该地址空间里存放的就是设备号

第二个参数:次设备号起始地址,

第三个参数:申请设备号的数量(主设备号不变,次设备号++)

第四个参数:名字(随便给)

申请完设备号后,把它加入cdev链表里

cpp 复制代码
struct cdev cdev; //定义cdev
struct file_operations led_fops = {
    .owner=THIS_MODULE,
    .open=led_open,
    .release=led_close,
    .write=led_write,
};
cdev_init(&cdev, &led_fops);  //用文件操作结构体初始化cdev
cdev_add(&cdev, dev, 1);     //添加设备号

也可以动态分配

cpp 复制代码
struct cdev *cdev; //定义cdev
cdev=cdev_alloc();
struct file_operations led_fops = {
    .owner=THIS_MODULE,
    .open=led_open,
    .release=led_close,
    .write=led_write,
};
cdev.ops=&fops;  //用文件操作结构体初始化cdev
cdev_add(cdev, dev, 1);     //添加设备号

这里不需要cdev_init 因为cdev_alloc 跟cdev_init 内操作一样,只是少了一个操作结构体赋值,所以单独补上。
接下里就是创建/dev/led

cpp 复制代码
    struct class *led;
    led = class_create(THIS_MODULE, "myled_class");
    device_create(led,NULL,dev,NULL,"led");

完整代码

cpp 复制代码
#include "linux/device.h"
#include "linux/export.h"
#include "linux/gpio.h"
#include "linux/module.h"
#include "linux/kernel.h"
#include "linux/init.h"
#include "linux/fs.h"
#include "linux/cdev.h"
#include "linux/uaccess.h"

dev_t dev;
struct cdev cdev;
struct class *led;
static int led_open (struct inode *a, struct file *b){

    return 0;
}
static int led_close (struct inode *a, struct file *b){

    return 0;
}
static ssize_t led_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
    char val;
    unsigned long a=copy_from_user(&val,buf,1);
    if(a)
    {

    }
    else
    {
    
    }
    if(val=='1')
    {
        printk("开灯\r\n");
        gpio_set_value(21,1);
        gpio_set_value(22,1);
        printk("ok\r\n");
    }    
    else
    {
        printk("关灯\r\n");
        gpio_set_value(21,0);
        gpio_set_value(22, 0);
        printk("ok\r\n");
    }
    return 0;
}
struct file_operations led_fops = {
    .owner=THIS_MODULE,
    .open=led_open,
    .release=led_close,
    .write=led_write,
};
static int __init led_init(void)
{
    //申请设备号
    int ret=  alloc_chrdev_region(&dev,0,1,"led_dev");
    if(ret<0)
    {
        return -1;   //加载失败
    }
    printk(KERN_INFO "LED driver loaded successfully\n");
    //初始化LINUX2.6 cdev结构体
    cdev_init(&cdev, &led_fops);
    cdev_add(&cdev, dev, 1);
    gpio_request(21,"led");
    gpio_direction_output(21, 0);
    gpio_request(22,"led");
    gpio_direction_output(22, 0);
    led = class_create(THIS_MODULE, "myled_class");
    device_create(led,NULL,dev,NULL,"led");

    return 0;
}
static void __exit led_exit(void)
{
    device_destroy(led, dev);
    class_destroy(led);
    cdev_del(&cdev);
    printk(KERN_INFO "LED driver unloaded successfully\n");
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
相关推荐
哲Zheᗜe༘19 分钟前
学习Ansible Playbook 核心语法
网络·学习·ansible
('-')23 分钟前
《从根上理解MySQL是怎样运行的》第三章学习笔记
笔记·学习·mysql
Nan_Shu_6145 小时前
学习:ES6(2)
前端·学习·es6
河铃旅鹿6 小时前
Android开发-java版:Framgent
android·java·笔记·学习
自动化代码美学8 小时前
【Python3.13】官网学习之控制流
开发语言·windows·python·学习
AA陈超9 小时前
ASC学习笔记0020:用于定义角色或Actor的默认属性值
c++·笔记·学习·ue5·虚幻引擎
檐下翻书17310 小时前
从入门到精通:流程图制作学习路径规划
论文阅读·人工智能·学习·算法·流程图·论文笔记
SalvoGao10 小时前
Python学习 | 怎么理解epoch?
数据结构·人工智能·python·深度学习·学习
思成不止于此11 小时前
深入理解 C++ 多态:从概念到实现的完整解析
开发语言·c++·笔记·学习·多态·c++40周年
Highcharts.js11 小时前
学习 Highcharts 可视化开发的有效途径
学习·数据可视化·highcharts·图表开发·可视化开发