【Linux 驱动】设备驱动程序再理解

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

★什么是驱动程序

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


设备驱动程序说白了(实质)就是为应用程序提供一组操作硬件设备的接口。驱动程序是可以直接操作硬件上的资源,例如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 驱动】设备驱动程序再理解,布布扣,bubuko.com

时间: 2025-01-02 16:49:32

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

20150216简单的Linux字符设备驱动程序

20150216简单的Linux字符设备驱动程序 2015-02-16 李海沿 关于字符设备驱动程序详细的知识点,本文就不再介绍了,很多同志,看了知识点,还是一头雾水,写不出来,所以,本文从实战出发,带领各位同胞们来实现一个字符设备驱动程序,改程序可作为字符设备的通用模板. 好了废话不多说,先上驱动程序,在驱动程序中加入详细注释: 1 /****************************** 2 linux 字符设备驱动程序 3 *****************************/

linux字符设备驱动程序源码分析

本文主要分析linux-2.6.28内核版本的字符设备抽象层源码文件char_dev.c.该文件代码量不大,但其为linux应用程序访问实际字符型硬件设备搭建了桥梁,进一步限定了linux字符设备驱动的设计框架. void __init chrdev_init(void) {  cdev_map = kobj_map_init(base_probe, &chrdevs_lock);  bdi_init(&directly_mappable_cdev_bdi); } 该函数在系统初始化启动时

11 Linux 块设备驱动程序

参考:https://www.cnblogs.com/big-devil/p/8590007.html Linux 块设备驱动程序 概念补充: 块 扇区是硬件数据传输的基本单元,块则是虚拟文件系统传输数据的基本单位.Linux内核中,块的大小必须是2的次幂,但不能超过一个页(4K)的大小. 段 同一物理页面中的硬盘存储介质上连续的多个块组成一个段.段的大小与块的个数有关,段包含多个块,块包含多个扇区.段在内核中由bio_vec结构体描述,多个段的信息存放于结构体bio中的biz_io_vec数组

linux字符设备驱动程序框架

#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/delay.h> #include <asm/uaccess.h> #include <asm/irq.h> #include <asm/io.h> #include <asm/a

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

#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/delay.h> #include <asm/uaccess.h> #include <asm/irq.h> #include <asm/io.h> #include <asm/a

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

前段时间在学习linux设备驱动的时候,看了陈学松著的<深入Linux设备驱动程序内核机制>一书. 说实话.这是一本非常好的书,作者不但给出了在设备驱动程序开发过程中的所须要的知识点(如对应的函数和数据结构),还深入到linux内核里去分析了这些函数或数据结构的原理.对设备驱动开发的整个过程和原理都分析的非常到位.但可能是因为知识点太多.原理也比較深的原因,这本书在知识点的排版上跨度有些大.所以读起来显得有点吃力,可是假设第一遍看的比較认真的话,再回头看第二次就真的可以非常好地理解作者的写作思

Linux驱动设备中的并发控制

一.基本概念 二.中断屏蔽 三.原子操作 四.自旋锁 五.信号量 六.互斥体 七.自旋锁与信号量的比较 Linux设备驱动中必须解决的一个问题是多个进程对共享资源的并发访问,并发的访问会导致竞态,即使是经验丰富的驱动工程师也常常设计出包含并发问题的bug驱动程序. Linux提供了多种解决竞态问题的方式,这些方式适合不同的应用场景. 一.基本概念 并发(concurrency):指的是多个执行单元同时.并行被执行,而并发的执行单元对共享资源(硬件资源和软件资源上的全局变量.静态变量等)的访问则很

[linux驱动]设备驱动模型相关(二)——常用API

1,在/sys/class/目录下创建一个设备节点,比如创建一个class_test_usb的设备节点 [cpp] view plaincopy static struct calss *test_class; test_class = class_creat(THIS_MODULE,"class_test_usb"); 2,在class_test_usb目录下创建另外一个设备节点android0,如下 [cpp] view plaincopy struct device *dev;

[linux驱动][linux驱动]设备驱动模型相关(一)——示例代码

1,以下为示例代码: [cpp] view plaincopy #include <linux/device.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/string.h> MODULE_LICENSE("Dual BSD/GPL"); static char *Version =