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");
相关推荐
dddaidai1233 小时前
kafka入门学习
分布式·学习·kafka
明月清了个风3 小时前
数据结构与算法学习笔记(Acwing 提高课)----动态规划·树形DP
笔记·学习·动态规划·树形dp
贩卖纯净水.4 小时前
webpack打包学习
前端·学习·webpack
虾球xz6 小时前
CppCon 2015 学习:Concurrency TS Editor’s Report
开发语言·c++·学习
Moonnnn.6 小时前
【电赛培训课程】运算放大器及其应用电路设计
笔记·学习
pop_xiaoli7 小时前
UI学习—cell的复用和自定义cell
学习·ui·ios
rui锐rui7 小时前
大模型学习
学习
YKPG8 小时前
C++学习-入门到精通【14】标准库算法
c++·学习·算法
potender8 小时前
前端基础学习html+css+js
前端·css·学习·html·js
靡樊9 小时前
Socket编程UDP\TCP
网络·c++·学习·tcp/ip·udp