【讯为Linux驱动开发】2.注册一个字符设备

【问】如何描述一个字符设备?

dev结构体

其中需要关心三个成员变量:

所属模块 :struct module *owner;

文件操作结构体: const struct file_operations *ops

设备号 : dev_t

当应用层使用指令open("/dev/hello", HELLO),系统就会进入驱动程序中执行cdev_open函数

【问】 如何连接系统调用open和驱动程序dev_open函数

file_operations结构体中就将这两个函数进行连接:

cs 复制代码
static struct file_operations cdev_ops = {
     .owner = THIS_MODULE;
     .open = cdev_open;
}
【问】应用程序和驱动程序的桥梁是什么?

设备节点,设备节点创建在/dev目录下。

比如 open("/dev/hello" ,HELLO);

【问】如何创建设备节点?

使用udev机制,在注册设备的时候自动创建,在注销设备的时候自动销毁。

1.创建类:

class_creat(struct module *owner ,const char *name)

THIS_MODULE 和 类的名字

对应删除:class_destroy(struct class *cls) 类

2.在类下创建设备:

device_creat(struct class *cls ,struct device *parent, dev_t devt , NULL ,const char *fmt )

1.哪个类 2.父设备是谁? NULL一般 3.设备号 4.NULL 5.设备节点的名字

3.删除类:

device_destroy(struct class *cls, dev_t devt)

类 设备号

【注册字符设备模版 】

cs 复制代码
static int major = 0;
static int minor = 0;
module_param(major ,int ,S_IRUGO);
module_param(minor ,int ,S_IRUGO);

dev_t dev_num;

static int cdev_open(struct inode *inode, struct file *filp)
{
    printk("cdev_open success\n");
    return 0;
}

static ssize_t cdev_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{
    printk("cdev_read success\n");
    return 0;
}

static ssize_t cdev_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{
    printk("cdev_write success\n");
    return 0;            
}

static int cdev_release(struct inode *inode, struct file *filp)
{
    printk("cdev_release success\n");
    return 0;       
}

struct file_operations cdev_file_operations = {
    .owner = THIS_MODULE;
    .open = cdev_open;
    .read = cdev_read;
    .write = cdev_write;
    .release = cdev_release;
}


struct cdev cdev_test;


static int moduleparam_init()
{
        int ret;
        /* 动态申请 */
        ret = alloc_chrdev_region(&dev_num,0,1);  
        if(ret<0)
        {
           printk("alloc_chrdev_region error\n");
        }
          //动态注册设备号成功,则打印
           printk("alloc_chrdev_region ok\n");  
           major_num =MAJOR(dev_num); //将主设备号取出来
           minor_num = MINOR(dev_num);//将次设备号取出来
           printk("major_num = %d\n",major_num);//打印传入进来的主设备号
           printk("minor_num = %d\n",minor_num);//打印传入进来的次设备号
           
           cdev_test.owner = THIS_MODULE;
           cdev_init(cdev_test, cdev_file_operations);
           cdev_add(&cdev_test, dev_num, 1);
           
           class = class_creat(THIS_MODULE, "test");
           device = device_creat(class,NULL,dev_num,,NULL,"/dev/test")
          
           return 0;
}

static void hello_exit(void)
{
  unregister_chrdev_region(MKDEV(major_num,minor_num),DEVICE_NUMBER);//注销设备号
  cdev_del(&cdev_test);  //销毁字符设备

  device_destroy(class,dev_num);
  class_destroy(class);

  printk("gooodbye! \n");
}

module_init(moduleparam_init);
module_init(moduleparam_exit);

【应用程序验证】

cs 复制代码
int main(int argc, char *argv[])
{
 int fd;
 char buf[64] = 0;
 fd = open("/dev/test", HELLO);  /* 打开设备节点 */   
 close(fd);
 return 0;  
}
【问】app.c如何编译?

使用3568开发板对应的交叉编译器

linux源码 / prebuilts /gcc /linux-x86 / aarch64 / gcc ..............................

然后进入bin文件夹找到 gnu - gcc

编译命令:

进入app.c目录:

交叉编译器的绝对路径 加 / 交叉编译器的名字 加 app.c

生成a.out文件

拷贝 a.outfile .ko 文件进开发板

加载:insmod file.ko

手动创建设备节点 : mknod /dev/test c 2350 (设备名字和驱动中一致)

(在dev/test中可以看到设备节点)

执行 a.out 应用程序: ./a.out

成功调用,打印出驱动中的这两句话:

实验效果:

加载:insmod file.ko

因为是自动创建设备节点,所以ls /dev/test直接看

执行:./a.out

---------------------------------------------

-----------------------打印出打开设备和卸载设备信息

相关推荐
嵌入式郑工4 小时前
RK3566 LubanCat 开发板 USB Gadget 配置完整复盘
linux·驱动开发·ubuntu
雾削木1 天前
树莓派 ESPHome 固件编译与烧录全攻略(解决超时与串口识别问题)
驱动开发
春日见2 天前
win11 分屏设置
java·开发语言·驱动开发·docker·单例模式·计算机外设
DarkAthena2 天前
【GaussDB】手动编译不同python版本的psycopg2驱动以适配airflow
驱动开发·python·gaussdb
松涛和鸣3 天前
DAY66 SPI Driver for ADXL345 Accelerometer
linux·网络·arm开发·数据库·驱动开发
嵌入式郑工3 天前
# RK3576 平台 RTC 时钟调试全过程
linux·驱动开发·ubuntu
GS8FG3 天前
针对Linux,RK3568平台下,I2C驱动的一点小小的领悟
linux·驱动开发
一路往蓝-Anbo3 天前
第 4 篇:策略模式 (Strategy) —— 算法的热插拔艺术
网络·驱动开发·stm32·嵌入式硬件·算法·系统架构·策略模式
A-花开堪折3 天前
RK3568 Android 11 驱动开发(五):串口驱动适配
驱动开发
bandaoyu4 天前
【RDMA】rdma指令
驱动开发