注册字符类设备-11

Posted 杨斌并

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了注册字符类设备-11相关的知识,希望对你有一定的参考价值。

注册字符类设备

  • 注册杂项设备:
misc_register(&misc_dev);
  • 注销杂项设备:
misc_deregister(&misc_dev);
  • cdev结构体:描述字符设备的一个结构体
  • 字符类设备的一些操作是在 #include <linux/cdev.h> 头文件下
struct cdev {
	struct kobject kobj;
	struct module *owner;
	const struct file_operations *ops;
	struct list_head list;
	dev_t dev;
	unsigned int count;
};
  1. 步骤一:定义一个cdev结构体
  2. 步骤二:使用cdev init 函数初始化cdev结构体成员变量
void cdev init(struct cdev *, const struct file_operations *);
  • 参数:
    第一个:要初始化的cdev
  • 第二个:文件操作集
    cdev->ops = fops;实际就是把文件操作集写个ops
  1. 步骤三:使用cdev_add函数注册到内核
int cdev_add(struct cdev *, dev_t, unsigned);

参数:

  • 第一个: cdev的结构体指针
  • 第二个:设备号
  • 第三个:次设备号的数量

设备的注销

void cdev_del(struct cdev *);

参数

  • 第一个 设备号

字符类设备注册后并不会自动生成设备节点

  • 我们需要使用 mknod 命令创建一个设备节点

  • 格式

    mknod 名称 类型 主设备号 次设备号
    
  • 举例 c 代表字符型

    mknod /dev/test c 247 0
    

    代码

    • app.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char *argv[]){
   int fd;
   char buf[64] = {0};
   char buf_write[64] = "write aaaaaaaaa";
   fd = open("/dev/test",O_RDWR);
   if (fd < 0)
   {
       printf("open error \\n");
       return fd;
   }
   // printf("open success \\n");
   // read(fd,buf,sizeof(buf));
   // write(fd,buf_write,sizeof(buf_write));
   // printf("buf is %s\\n",buf);
   // close(fd);
   return 0;
}
  • chrdev.c
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>
//设备的数量
#define DEVICE_NUMBER 1
//静态名称
#define DEVICE_SNAME "schrdev"
//动态名称
#define DEVICE_ANAME "achrdev"
//次设备号的起始地址
#define DEVICE_MINOR_NUMBER 0

//主设备号,次设备号
static int major_num, minor_num;

struct cdev cdev;

module_param(major_num,int,S_IRUSR);
module_param(minor_num,int,S_IRUSR);

int chrdev_open(struct inode * inode, struct file * file){

   printk("chrdev_open 已经打开了");
   return 0;

}

struct file_operations chrdev_ops =
{

   .owner = THIS_MODULE,
   .open = chrdev_open, 
 
};


static int hello_init(void){

   dev_t dev_num;
   int ret;

   if (major_num)
   {
       dev_num = MKDEV(major_num, minor_num);

       printk("major_num = %d \\n",major_num);
       printk("minor_num = %d \\n",minor_num);

       ret = register_chrdev_region(dev_num,DEVICE_NUMBER,DEVICE_SNAME);

       if (ret <0 )
       {
           printk("register_chrdev_region 注册失败了 \\n");
       }

       printk("register_chrdev_region 注册成功了 \\n");      

   }else 
   {

       ret = alloc_chrdev_region(&dev_num, DEVICE_MINOR_NUMBER, DEVICE_NUMBER, DEVICE_ANAME);
       if (ret < 0 )
       {
           printk("alloc_chrdev_region 失败了 \\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);

       printk("alloc_chrdev_region 成功了 \\n");
       
   }


   cdev.owner = THIS_MODULE;
   cdev_init(&cdev, &chrdev_ops);

   cdev_add(&cdev, dev_num, DEVICE_NUMBER);
   
   
   printk(KERN_ALERT "Hello , World\\n"); //内核空间里没有printf,用printk
   return 0;

}

static void hello_exit(void){
   unregister_chrdev_region(MKDEV(major_num, minor_num), DEVICE_NUMBER);
   cdev_del(&cdev);
   printk(KERN_ALERT "Goodbye 注销成功 , World\\n");
}

//模块的注册
module_init(hello_init);
//模块的卸载
module_exit(hello_exit);
MODULE_LICENSE("Dual BSD/GPL");

以上是关于注册字符类设备-11的主要内容,如果未能解决你的问题,请参考以下文章

Linux——Linux驱动之字符类设备驱动编写实践,从0到1手把手教你字符类设备如何申请设备号,如何注册设备,如何自动创建设备节点

Linux字符设备驱动注册流程

申请字符类设备号-10

字符设备之register_chrdev与register_chrdev_region(转)

自动创建字符设备驱动的设备文件结点

如何在片段类的列表视图中显示 SQLite 数据库?