一。使用字符设备驱动程序

  1. 编译/安装驱动

    在Linux系统中,驱动程序通常采用内核模块的程序结构来进行编码。因此,编译/安装一个驱动程序,其实质就是编译/安装一个内核模块

  2. 创建设备文件

    通过字符设备文件,应用程序可以使用相应的字符设备驱动程序来控制字符设备。

    创建字符设备文件的方法一般有两种:

    1.使用mknod命令mknod/dev/文件名c 主设备号  次设备号

       查询设备号的命令  cat /proc/devices

    2. 使用函数在驱动程序中创建(后续课程介绍)

  编写应用程序时,使用命令 arm-linux-readelf  -d write_mem

  3. 访问设备

    编写应用程序访问设备。

    编写了write_mem.c 和read_mem.c 访问文件为  /dev/memdev0  驱动为memdev

    write_mem.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> int main()
{
int fd = ;
int src = ;
fd = open("/dev/memdev0",O_RDWR); write(fd,&src,sizeof(int));
close(fd); return ; }

  read_mem.c

int main()
{
int fd = ;
int dst = ; fd = open("dev/memdev0",O_RDWR); read(fd,&dst,sizeof(int)); printf("dst is %d\n",dst); }

二。 字符设备驱动模型

  1. 设备描述结构 cdev

    在任何一种驱动模型中,设备都会用内核中的一种结构来描述。

    我们的字符设备在内核中使用struct  cdev来描述。

    struct  cdev

    {

       structkobjectkobj;

       structmodule *owner;

       const structfile_operations*ops;   //设备操作集

       structlist_headlist;

       dev_tdev;  //设备号

       unsigned intcount; //设备数

    };

    (1).字符设备文件与字符驱动程序如何建立起对应关系??

        答案:主设备号

        驱动程序什么来区分串口1和串2

        答案:次设备号

    (2).Linux内核中使用dev_t类型来定义设备号,dev_t这种类型其实质为32位的unsigned int,

        其中高12位为主设备号,低20位为次设备号.

        问1:如果知道主设备号,次设备号,怎么组合成dev_t类型

        答:dev_t dev = MKDEV(主设备号,次设备号)

        问2: 如何从dev_t中分解出主设备号?

        答: 主设备号= MAJOR(dev_t dev)

        问3: 如何从dev_t中分解出次设备号?

        答: 次设备号=MINOR(dev_t dev)

    (3).如何为设备分配一个主设备号?

        #静态申请开发者自己选择一个数字作为主设备号,然后通过函数register_chrdev_region向内核申请使用。

        缺点:如果申请使用的设备号已经被内核中的其他驱动使用了,则申请失败。使用的设备号已经被内核中的其他驱动使用了,则申请失败。

        #动态分配使用alloc_chrdev_region由内核分配一个可用的主设备号。优点:因为内核知道哪些号已经被使用了,所以不会导致分配到已经被使用的号。

    (4).不论使用何种方法分配设备号,都应该在驱动退出时,使用unregister_chrdev_region函数释放这些设备号

     (5). Struct file_operations是一个函数指针的集合,定义能在设备上进行的操作。

       结构中的函数指针指向驱动中的函数, 这些函数实现一个针对设备的操作, 对于不支持的操作则设置函数指针为NULL。

       例如:struct file_operations dev_fops =

          {

            .llseek= NULL,

            .read= dev_read,

            .write= dev_write,

            .ioctl= dev_ioctl,

            .open= dev_open,

            .release= dev_release,

          };

  2. 字符设备驱动模型

    1. 驱动初始化

      2.1.1 分配设备描述结构

         cdev变量的定义可以采用静态和动态两种办法

         •静态分配struct cdev mdev;

         •动态分配struct cdev *pdev = cdev_alloc();

      2.1.2 初始化设备描述结构

         struct cdev的初始化使用cdev_init函数来完成。

         cdev_init(struct cdev *cdev, const struct file_operations *fops)

         参数:cdev: 待初始化的cdev结构

            fops: 设备对应的操作函数集

      2.1.3 注册设备描述结构

         字符设备的注册使用cdev_add函数来完成。

         cdev_add(struct cdev *p, dev_t dev, unsigned count)

         参数:p: 待添加到内核的字符设备结构

            dev: 设备号

            count: 该类设备的设备个数

      2.1.4 硬件初始化

    2. 实现设备操作

      1. open

        int (*open) (struct inode *, struct file *)打开设备,响应open系统

        open设备方法是驱动程序用来为以后的操作完成初始化准备工作的。

        在大部分驱动程序中,open完成如下工作:

        #标明次设备号

        #启动设备

      2. read

        ssize_t (*read) (struct file *, char __user *, size_t, loff_t *)从设备读取数据,响应read系统调用

        read设备方法通常完成2件事情:

        #从设备中读取数据(属于硬件访问类操作)

        #将读取到的数据返回给应用程序

        ssize_t (*read) (struct file *filp, char __user *buff, size_t count, loff_t *offp)

        参数分析:filp:与字符设备文件关联的file结构指针, 由内核创建.

             buff : 从设备读取到的数据,需要保存到的位置。由read系统调用提供该参数。

             count: 请求传输的数据量,由read系统调用提供该参数。

             offp: 文件的读写位置,由内核从file结构中取出后,传递进来。

      3. write

        ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *)向设备写入数据,响应write系统调用

        write设备方法通常完成2件事情:

        #从应用程序提供的地址中取出数据

        #将数据写入设备(属于硬件访问类操作)

      4. lseek

        loff_t (*llseek) (struct file *, loff_t, int)重定位读写指针,响应lseek系统调用

      5. close

        int (*release) (struct inode *, struct file *);关闭设备,响应close系统调用

        release方法的作用正好与open相反。

        这个设备方法有时也称为close,它应该:

        #关闭设备

    3. 驱动注销

      当我们从内核中卸载驱动程序的时候,需要使用cdev_del函数来完成字符设备的注销。

  3. 范例驱动分析

    

Linux 字符设备驱动模型的更多相关文章

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

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

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

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

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

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

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

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

  5. Linux字符设备驱动实现

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

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

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

  7. linux设备驱动之字符设备驱动模型(2)

    在上一篇中我们已经了解了字符设备驱动的原理,也了解了应用层调用内核函数的机制,但是我们每次操作设备,都必须首先通过mknod命令创建一个设备文件名,比如说我们要打开u盘,硬盘等这些设备,难道我们还要自 ...

  8. linux设备驱动之字符设备驱动模型(1)

    一:字符设备驱动 在linux下面,应用层看到的一切皆为文件(名字)所有的设备都是文件,都可以调用open,read,write来操作,而在内核中每个中每个设备有唯一的对应一个设备号: APP   ( ...

  9. Linux字符设备驱动框架

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

随机推荐

  1. OC:NSmuber、NSString 的互转

    NSmuber 转化为 IOS 中的 NSString 假设现有一NSNumber的变量A,要转换成NSString类型的B 方法如下: NSNumberFormatter* numberFormat ...

  2. 重学HTML

    http://www.imooc.com/learn/9 1.em/strong 如果想在一段话中特别强调某几个文字,这时候就可以用到<em>或<strong>标签. 但两者在 ...

  3. iOS开发-基本的网络知识

    一.HTTP协议的主要特点:(摘自 仰望星空 的博客)重点内容 1. CS模式 2. 简单快速:只需要传送请求方法和路径.(常用方法有GET,HEAD,POST) 3. 灵活:任意对象都可以,类型由C ...

  4. java.util.Date转java.sql.Date丢失时间问题

    java.sql.Date 只存储日期数据不存储时间数据// 会丢失时间数据preparedStatement.setDate(1, new java.sql.Date(date.getTime()) ...

  5. 【转】 解决IllegalStateException: Can not perform this action after onSaveInstanceState

    今天使用Fragment的时候,出现了这个错误 IllegalStateException: Can not perform this action after onSaveInstanceState ...

  6. Why isn't there a SendThreadMessage function?

    Here's an interesting customer question: Windows has PostMessage and SendMessage. It also has PostTh ...

  7. CodeForces 163B Lemmings 二分

    Lemmings 题目连接: http://codeforces.com/contest/163/problem/B Descriptionww.co As you know, lemmings li ...

  8. 使用NuGet安装EntityFramework4.2

    1.下载NuGet 有两种方式下载NuGet 第一种:在微软的档案库下载,下载地址为:http://visualstudiogallery.msdn.microsoft.com/27077b70-9d ...

  9. iOS开发——多线程OC篇&(十)多线程NSOperation基本使用

    NSOperation基本操作 一.并发数 (1)并发数:同时执⾏行的任务数.比如,同时开3个线程执行3个任务,并发数就是3 (2)最大并发数:同一时间最多只能执行的任务的个数. (3)最⼤大并发数的 ...

  10. php-cli模式学习(PHP命令行模式)(转)

    之前知道php—cli模式是一种类似shell命令式的执行php程序,不过一直以为这个是一种落后的方式,应该没有什么意义,因为从没有遇到过使用这个cli模式编程的.不过今天遇到了使用cli模式的应用. ...