学习设备驱动编程也有一段时间了,也写过了几个驱动程序,因此有对设备驱动程序有了一些新的理解和认识,总结一下。学习设备驱动编程也有一段时间了,也写过了几个驱动程序。因此有对设备驱动程序有了一些新的理解和认识,总结一下。

★什么是驱动程序

刚開始学习设备驱动程序的时候,产生了很多的问题。什么是驱动程序?驱动程序是干嘛的?它是怎样工作的?它又是怎样跟操作系统联系起来的?一系列的问题,如今有些地方还是不一定清楚,可是相比起刚開始的那个阶段,感觉自己还是清楚了非常多。


设备驱动程序说白了(实质)就是为应用程序提供一组操作硬件设备的接口。

驱动程序是能够直接操作硬件上的资源,比如GPIO的各个寄存器,从而控制GPIO的方向(输出或是输入)、引脚的电平高低、中断等等。

驱动程序所做的事情大部分与直接在51单片机或是AVR单片机写的程序的功能相似,与它们不同的是驱动程序向上是为操作系统提供统一的接口的。

★file_operations结构体

驱动设备有非常多种,那么驱动它们的程序也会各有不同,那么驱动程序如何向上提供统一的接口呢?最关键的就是这个结构体,它定义在include/linux/fs.h文件里

struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *, fl_owner_t id);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, struct dentry *, int datasync);
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
int (*check_flags)(int);
int (*dir_notify)(struct file *filp, unsigned long arg);
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
};

通过这个结构体将驱动程序中操作硬件资源的函数链接起来。那么当操作系统知道了这个结构体之后,也就是知道了这个驱动程序。那么操作系统怎样知道这个结构体呢?

事实上。Linux下设备大概能够分为两种:字符设备、块设备。内核中用2个全局变量存放这两类驱动程序:

字符设备重要的结构体:

static struct char_device_struct {
struct char_device_struct *next;
unsigned int major;
unsigned int baseminor;
int minorct;
char name[64];
struct file_operations *fops;
struct cdev *cdev; /* will die */
} *chrdevs[CHRDEV_MAJOR_HASH_SIZE];

当驱动程序调用register_chrdev(unsigned int major, const char * name, struct file_operations *fops)注冊函数就是将file_operations结构体存放到数组chrdevs[CHRDEV_MAJOR_HASH_SIZE]数组中,数组下标就是驱动主设备号。这样驱动程序就能和内核有了关联。

★设备文件

设备节点有什么用呢?我们知道在Liunx下,设备都是以文件的形式存在的。驱动程序执行在内核中,应用程序訪问驱动程序是通过系统利用系统函数訪问设备文件。

因此文件系统中一定要有一个设备文件与你的设备驱动程序相相应,这样应用程序才干訪问你的设备驱动程序。

设备文件一般放在/dev文件夹以下。你能够通过ls 命令查看。如何创建设备文件节点呢?

能够使用mknod命令,比如我要创建一个主设备号为103。次设备号为0的字符设备文件。则能够输入:mknod /dev/XXX c 103 0 当中/dev/XXX中的XXX表示设备文件的名称

【Linux 驱动】设备驱动程序再理解的更多相关文章

  1. (linux)块设备驱动程序

      1.4.1  Linux块设备驱动程序原理(1) 顾名思义,块设备驱动程序就是支持以块的方式进行读写的设备.块设备和字符设备最大的区别在于读写数据的基本单元不同.块设备读写数据的基本单元为块,例如 ...

  2. 浅析Linux字符设备驱动程序内核机制

    前段时间在学习linux设备驱动的时候,看了陈学松著的<深入Linux设备驱动程序内核机制>一书. 说实话.这是一本非常好的书,作者不但给出了在设备驱动程序开发过程中的所须要的知识点(如对 ...

  3. ARM Linux字符设备驱动程序

    1.主设备号和次设备号(二者一起为设备号): 一个字符设备或块设备都有一个主设备号和一个次设备号.主设备号用来标识与设备文件相连的驱动程序,用来反  映设备类型.次设备号被驱动程序用来辨别操作的是哪个 ...

  4. 一个简单的演示用的Linux字符设备驱动程序

    实现如下的功能:--字符设备驱动程序的结构及驱动程序需要实现的系统调用--可以使用cat命令或者自编的readtest命令读出"设备"里的内容--以8139网卡为例,演示了I/O端 ...

  5. 简单linux块设备驱动程序

    本文代码参考<LINUX设备驱动程序>第十六章 块设备驱动程序 本文中的“块设备”是一段大小为PAGE_SIZE的内存空间(两个扇区,每个扇区512字节) 功能:向块设备中输入内容,从块设 ...

  6. 简单linux字符设备驱动程序

    本文代码参考<LINUX设备驱动程序>第三章 字符设备驱动程序 本文中的“字符设备”是一段大小为PAGE_SIZE的内存空间 功能:向字符设备写入字符串:从字符设备读出字符串 代码: 1. ...

  7. Linux驱动设备中的并发控制

    一.基本概念 二.中断屏蔽 三.原子操作 四.自旋锁 五.信号量 六.互斥体 七.自旋锁与信号量的比较 Linux设备驱动中必须解决的一个问题是多个进程对共享资源的并发访问,并发的访问会导致竞态,即使 ...

  8. linux驱动之jiffies的理解

    本文主要借鉴了http://blog.csdn.net/allen6268198/article/details/7270194,非常感谢该网友的分享. 在LINUX的时钟中断中涉及至二个全局变量一个 ...

  9. linux字符设备驱动程序框架(老方法)

    #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #inclu ...

随机推荐

  1. 利用ItextSharp产PDF完整操作

    记得上回有写到用C#操作Excel(.net 4.0) 很多朋友说推荐用NPOI,的确,用微软自带的操作execl会有很大的问题.客户的主机不愿意安装excel, 这时我才意识到用自带组件完全是不行的 ...

  2. linux 系统的负载与CPU、内存、硬盘、用户数监控脚本[marked]

    转载文章 原始出处  在没有nagios监控的情况下,只要服务器能上互联网,就可通过发邮件的方式来提醒管理员系统资源的使用情况. 一.编写linux系统告警邮件脚本 # vim /scripts/sy ...

  3. 转 linux任务调度之crontab命令

    crontab命令常见于Unix和Linux的操作系统之中,用于设置周期性被执行的指令.该命令从标准输入设备读取指令,并将其存放于"crontab"文件中,以供之后读取和执行. 在 ...

  4. 牛客小白月赛3 B 躲藏【动态规划/字符串出现cwbc子序列多少次】

    链接:https://www.nowcoder.com/acm/contest/87/B来源:牛客网 XHRlyb和她的小伙伴Cwbc在玩捉迷藏游戏 Cwbc藏在多个不区分大小写的字符串中. 好奇的X ...

  5. 线段树【p2629】 好消息,坏消息

    顾z 你没有发现两个字里的blog都不一样嘛 qwq 题目描述-->p2629 好消息,坏消息 历程 刚开始看到这个题,发现是需要维护区间和,满心欢喜敲了一通线段树,简单debug之后交上去 \ ...

  6. SQL PARTITION BY:列值改变时重置计数

    现有数据如下: 需求:以科目为单位 对分数进行排序 SELECT *, ROW_NUMBER() OVER (PARTITION BY 科目 ORDER BY 分数 DESC) AS NUM FROM ...

  7. (转)stage 3d or unity 3d

    这个是这样子的.stage3d如果不使用flascc的话,性能会卡在as上面.你没卡是因为你用的效果还不够高级.往深了走的高端应用就是卡as性能上.这不是你代码能优化了的.我们后来都改用flascc写 ...

  8. Laravel 使用firstOrCreate 报错MassAssignmentException

    今天尝试使用firstOrCreate去优化一段查找不到即创建的代码,结果发现会报MassAssignmentException错误,提示我参数错误,去网上找了好久没有找到结果,最后庆幸自己解决了,把 ...

  9. Word中如何设置图片与段落的间距为半行

    第一种: 正文为5号,那么图片或者Viso对象前后空一行,设置字号为7号或者更小,这样设置的间距就是那个7号字的间距,比5号小,看着空白不是那么大. 第二种: Visio对象转为jpg,然后选中图片和 ...

  10. DevExpress.XtraTreeList

    1. DevExpress.XtraTreeList控件         将其简称为tree,tree其实就是一个树表控件,他像树一样包含具有父子关系的若干节点,同时每个节点又是一个带有多个字段的记录 ...