字符驱动(按键)初始化函数分析:

 int charDrvInit(void)
 {

     devNum = MKDEV(reg_major, reg_minor);

     printk(KERN_EMERG"devNum is %d\r\n", devNum);
     if(OK == register_chrdev_region(devNum, subDevNum, DEVICE_NAME))//subdevnum:要申请的第一个次设备号
     {
         printk(KERN_EMERG"register_chrdev_region ok\r\n");
     }
     else
     {
         printk(KERN_EMERG"register_chrdev_region error\r\n");
         return ERROR;
     }
16
 /**
  * register_chrdev_region() - register a range of device numbers
  * @from: the first in the desired range of device numbers; must include
  *        the major number.
  * @count: the number of consecutive device numbers required
  * @name: the name of the device or driver.
  *
  * Return value is zero on success, a negative error code on failure.
  */
 int register_chrdev_region(dev_t from, unsigned count, const char *name) //count = 1
 {
     struct char_device_struct *cd;
 static struct char_device_struct {
     struct char_device_struct *next;
     unsigned int major;
     unsigned int baseminor;
     int minorct;
     ];
     struct cdev *cdev;        /* will die */
 } *chrdevs[CHRDEV_MAJOR_HASH_SIZE];

struct char_device_struct

     dev_t to = from + count;
     dev_t n, next;

     for (n = from; n < to; n = next) {
         next = MKDEV(MAJOR(n)+, );/*先得到下一个设备号(其实也是一个设备号,只不过此时的次设备号为0)并存储于next中*/
18         if (next > to) /*溢出的情况*/          /*判断在from的基础上再追加count个设备(dev_t to = from+count)是否已经溢出到下一个主设备号*/
             next = to;
/*           如果没有溢出(next小于to),那么整个for语句就只执行个一次__register_chrdev_region函数;
             否则当设备号溢出时,会把当前溢出的设备号范围划分为几个小范围,分别调用__register_chrdev_region函数。  */
 
 /*
  * Register a single major with a specified minor range.
  *
  * If major == 0 this functions will dynamically allocate a major and return
  * its number.
  *
  * If major > 0 this function will attempt to reserve the passed range of
  * minors and will return zero on success.
  *
  * Returns a -ve errno on failure.
  */
 static struct char_device_struct *
13 __register_chrdev_region(unsigned int major, unsigned int baseminor,
14                int minorct, const char *name)
 {
     struct char_device_struct *cd, **cp;
     ;
     int i;

     cd = kzalloc(sizeof(struct char_device_struct), GFP_KERNEL);
     if (cd == NULL)
         return ERR_PTR(-ENOMEM);

     mutex_lock(&chrdevs_lock);

     /* temporary */
//此if语句目的在于如果主设备号为零,则自动分配主设备号(寻找设备号列表中的空的位置(从大到小))并返回
     ) {
         ; i > ; i--) {
             if (chrdevs[i] == NULL)
                 break;
         }

         ) {
             ret = -EBUSY;
             goto out;
         }
         major = i;
         ret = major;
     }
 //新元素赋值
     cd->major = major;
     cd->baseminor = baseminor;
     cd->minorct = minorct;
     strlcpy(cd->name, name, sizeof(cd->name));

     i = major_to_index(major);
 
 /* index in the above */
 static inline int major_to_index(unsigned major)
 {
     return major % CHRDEV_MAJOR_HASH_SIZE;
 }

//寻找新元素插入的位置

     for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next)
         if ((*cp)->major > major ||
             ((*cp)->major == major &&
              (((*cp)->baseminor >= baseminor) ||
               ((*cp)->baseminor + (*cp)->minorct > baseminor))))
             break;

     /* Check for overlapping minor ranges.  */
     if (*cp && (*cp)->major == major) {//如果当前元素存在并且主设备号和要添加的主设备号一致
         int old_min = (*cp)->baseminor;//更新旧的最小值,值为当前元素的次设备号
         ;////更新旧的最大值,值为当前次设备号+要申请号的设备个数-1,-1是因为从0开始的次设备号
         int new_min = baseminor;//新的最小值为要添加的次设备号
         ;
 //新的最大值为要添加的次设备号+要申请号的设备个数-1,-1是因为次设备号从0开始
         /* New driver overlaps from the left.  */
//显然生成的新的值必须要大于旧的最大值或者小于旧的最小值
         if (new_max >= old_min && new_max <= old_max) {
             ret = -EBUSY;
             goto out;
         }

         /* New driver overlaps from the right.  */
         if (new_min <= old_max && new_min >= old_min) {
             ret = -EBUSY;
             goto out;
         }
     }

     cd->next = *cp;
     *cp = cd;
     mutex_unlock(&chrdevs_lock);
     return cd;
 out:
     mutex_unlock(&chrdevs_lock);
     kfree(cd);
     return ERR_PTR(ret);
 }

         if (IS_ERR(cd))
             goto fail;
     }
     ;
 fail:
     to = n;
     for (n = from; n < to; n = next) {
         next = MKDEV(MAJOR(n)+, );
         kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));
     }
     return PTR_ERR(cd);
 }

     gDev = kzalloc(sizeof(struct cdev), GFP_KERNEL);
     gFile = kzalloc(sizeof(struct file_operations), GFP_KERNEL);

     gFile->open = butsOpen;
 //注册设备函数到file_operations结构体gFile

    //gDev->owner = THIS_MODULE;
     gFile->owner = THIS_MODULE;
     cdev_init(gDev, gFile);
 //在cdev结构体中添加指针指向file_operations结构体gFile
     cdev_add(gDev, devNum, );
 //建立设备号与cdev结构体联系
     printk(KERN_EMERG"button driver initial done...\r\n");
     ;
 }

Linux字符设备驱动--No.3的更多相关文章

  1. 深入理解Linux字符设备驱动

    文章从上层应用访问字符设备驱动开始,一步步地深入分析Linux字符设备的软件层次.组成框架和交互.如何编写驱动.设备文件的创建和mdev原理,对Linux字符设备驱动有全面的讲解.本文整合之前发表的& ...

  2. Linux字符设备驱动结构(一)--cdev结构体、设备号相关知识机械【转】

    本文转载自:http://blog.csdn.net/zqixiao_09/article/details/50839042 一.字符设备基础知识 1.设备驱动分类 linux系统将设备分为3类:字符 ...

  3. Smart210学习记录----beep linux字符设备驱动

    今天搞定了beep linux字符设备驱动,心里还是很开心的,哈哈...但在完成的过程中却遇到了一个非常棘手的问题,花费了我大量的时间,,,, 还是把问题描述一下吧,好像这个问题很普遍的,网上许多解决 ...

  4. Linux字符设备驱动实现

    Linux字符设备驱动实现 要求 编写一个字符设备驱动,并利用对字符设备的同步操作,设计实现一个聊天程序.可以有一个读,一个写进程共享该字符设备,进行聊天:也可以由多个读和多个写进程共享该字符设备,进 ...

  5. Linux字符设备驱动基本结构

    1.Linux字符设备驱动的基本结构 Linux系统下具有三种设备,分别是字符设备.块设备和网络设备,Linux下的字符设备是指只能一个字节一个字节读写的设备,不能随机读取设备内存中某一数据,读取数据 ...

  6. (57)Linux驱动开发之三Linux字符设备驱动

    1.一般情况下,对每一种设备驱动都会定义一个软件模块,这个工程模块包含.h和.c文件,前者定义该设备驱动的数据结构并声明外部函数,后者进行设备驱动的具体实现. 2.典型的无操作系统下的逻辑开发程序是: ...

  7. Linux字符设备驱动框架

    字符设备是Linux三大设备之一(另外两种是块设备,网络设备),字符设备就是字节流形式通讯的I/O设备,绝大部分设备都是字符设备,常见的字符设备包括鼠标.键盘.显示器.串口等等,当我们执行ls -l ...

  8. Linux 字符设备驱动模型

    一.使用字符设备驱动程序 1. 编译/安装驱动 在Linux系统中,驱动程序通常采用内核模块的程序结构来进行编码.因此,编译/安装一个驱动程序,其实质就是编译/安装一个内核模块 2. 创建设备文件 通 ...

  9. linux字符设备驱动学习笔记(一):简单的字符设备驱动

    最近在鼓捣lnux字符设备驱动,在网上搜集的各种关于linux设备驱动的代码和注释,要么是针对2.4的,要么是错误百出,根本就不能运行成功,真希望大家在发博客的时候能认真核对下代码的正确性,特别是要把 ...

  10. Linux字符设备驱动

    一.字符设备基础 字符设备 二.字符设备驱动与用户空间访问该设备的程序三者之间的关系 三.字符设备模型 1.Linux内核中,使用 struct cdev 来描述一个字符设备 动态申请(构造)cdev ...

随机推荐

  1. oracle获得ddl语句

    dbms_metadata.get_ddl()用于获取对象的DDL,其具体用法如下.注意:在sqlplus里,为了更好的展示DDL,需要设置如下参数:set line 200set pagesize ...

  2. 040同步条件event

    条件同步和条件变量同步差不多意思,只是少了锁功能,因为条件同步设计于不访问共享资源的条件环境,event=threading.Event():条件环境对象,初始值为False.event.isSet( ...

  3. SkyWalking 为.NET Core

    SkyWalking 为.NET Core https://www.cnblogs.com/liuhaoyang/p/skywalking-dotnet-v02-release.html Apache ...

  4. 【我所认知的BIOS】—> uEFI AHCI Driver(8) — Pci.Read()

    [我所认知的BIOS]-> uEFI AHCI Driver(8) - Pci.Read() LightSeed 6/19/2014 社会一直在变.不晓得是不是社会变的太苦开,而我没变所以我反而 ...

  5. C# 面向对象之多态

    //多态:让一个对象表现的多种状态 //实现:子类重写父类的虚方法 Person person = new Person(); Chinese chinese = new Chinese(); Ame ...

  6. div拖动

    <!DOCTYPE html><html xmlns:th="http://www.thymeleaf.org"><head> <meta ...

  7. CSS3-阴影参数基础

    box-shadow 语法:text-shadow: x-shadow y-shadow distance color; 值  描述  x-shadow  必需.水平阴影的位置.允许负值. y-sha ...

  8. mdev自动创建和删除设备节点

    设备节点的创建有二种方法: 1)手动创建:mknode命令  当insmod后,还需要手动moknod创建设备节点才能被应用层打开,并且使用完成之后还要删除节点. 2) 自动创建:mdev mdev, ...

  9. 一点一点看JDK源码(三)java.util.ArrayList 前偏

    一点一点看JDK源码(三)java.util.ArrayList liuyuhang原创,未经允许禁止转载 本文举例使用的是JDK8的API 目录:一点一点看JDK源码(〇) 1.综述 ArrayLi ...

  10. Swift_属性

    Swift_属性 点击查看源码 class DataImporter { var fileName = "data.txt" init() { print("初始化&qu ...