百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 优雅编程 > 正文

嵌入式Linux内核的驱动程序开发是怎样的

sinye56 2024-10-30 03:56 9 浏览 0 评论

Linux设备驱动程序在Linux内核源代码中占有很大比例,从2.0、2.2到 2.4版本的内核,源代码的长度日益增加,其实主要是设备驱动程序在增加。它是一个遵循POSIX标准的免费操作系统。具有BSD和SYSV的扩展特性。与其他操作系统相比,嵌入式Linux系统以其可应用于多种硬件平台、内核高效稳定、源码开放、软件丰富、网络通信和文件管理机制完善等优良特性而正被作为研究热点,越来越多的研究人员采用Linux平台来开发自己的产品。

嵌入式进阶教程分门别类整理好了,看的时候十分方便,由于内容较多,这里就截取一部分图吧。

需要的朋友私信【内核】即可领取

内核学习地址:Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈-学习视频教程-腾讯课堂

设备驱动程序的编写

设备驱动程序是linux内核的一部分,是操作系统内核和机器硬件之间的接口,它由一组函数和一些私有数据组成,是连接应用程序与具体硬件的桥梁。Linux的一个基本特点是它对硬件设备的管理抽象化,系统中的每一个设备都用一个特殊的文件来表示。所有的硬件设备都像普通的文件一样看待,使用与操作系统相同的标准系统来进行打开、读写和关闭。

在Linux 操作系统下有3类主要的设备文件类型:块设备、字符设备、网络设备。字符设备是指存取时没有缓存的设备。可以像文件一样访问字符设备,字符设备驱动程序负责实现这些行为。系统的控制台和并口就是字符设备的例子,它们可以很好地用“流”来描述。块设备是文件系统的宿主,如磁盘。 Linux允许像字符设备那样读取块设备——允许一次传输任意数目的字节。结果是,字符设备和块设备读取数方式一致。而网络设备不同于字符设备和块设备, 它面向的上一层不是文件系统而是网络协议层,是通过BSD套接口访问数据。与设备相对应的是三类设备驱动程序,字符设备驱动程序、块设备驱动程序、网络设备驱动程序。

字符设备驱动程序、块设备驱动程序与网络设备驱动程序的结构体是不同的。

在linux 源代码linux/ include / linux/ fs. h中定义了字符设备和块设备驱动程序中必须使用的file_operaTIons结构,每个设备驱动都实现这个接口所定义的部分或全部函数。随着内核的不断升级, file_operaTIons结构也越来越大,不同的版本的内核会稍有不同。file_operaTIons定义如下:

struct file_operaTIons{
int( * lseek) ( struct inode * , struct file * , off_t , int) ; int( *release) ( struct inode * , struct file * ) ;
int( * read) ( struct inode * , struct file * , char * , int) ; int( * fsync) ( struct inode *, struct file * ) ;
int( *write) ( struct inode * , struct file * , const char *, int) ; int( * fasync) ( struct inode * , struct file *, int) ;
int( * readdir) ( struct inode , struct file , void * , dilldir) ; int( *check_media_change) ( kdev_t dev) ;
int(*select) ( struct inode *, struct file * , int, select_table * ) ; int( * revalidate) ( kdev_t dev) ; };
int ( * ioctl) ( struct inode * , struct file *, unsigned int, unsigned long) ;
int( *mmap) ( struct inode * , struct file * , struct vm_area_struct * ) ;
int( * open) ( struct inode *, struct file *) ;

应用程序只有通过对设备文件的open、release、read、write、ioctl等才能访问字符设备和块设备。用户自己定义好 file_operaTIons结构后,编写出设备实际所需要的各操作函数,对于不需要的操作函数用NULL初始化,这些操作函数将被注册到内核,当应用程序对设备相应的设备文件进行文件操作时,内核会找到相应的操作函数,并进行调用。如果操作函数使用NULL,操作函数就进行默认处理。

  1. 对于字符设备而言,llseek( ),read( ),write(),ioctl( ),open( ),release( )这些函数是不可缺的;
  2. 对于这块设备,open( ),release( ),ioctl(),check_media_change( ),revalidate( )是不可缺少的。

网络设备结构图 net_device 定义在 includelinuxnetdevice.h 里面,如下所示:

struct net_device
{
char name ; int (*init)(struct
net_device *dev);
unsigned short flags ; int (*open)
(struct net_device *dev);
unsigned long base_addr; int
(*stop)(struct net_device *dev)
unsigned int irq ; int
(*hard_start_xmit)(struct sk_buff *skb,
unsigned char dev_addr; struct
net_device *dev);
unsigned char addr_len; int
(*set_mac_address)( struct net_device
unsigned long trans_start; *dev,void* addr);
……
}

定义好net_device结构体后,根据实际情况编写操作函数,其中hard_start_xmit()函数是用来发送数据的,set_mac_address()是进行网络参数设置的。

当linux初始化时将调用初始化函数int device_init( ),该函数包括以下内容:

注册所用设备。linux用设备号来标识字符设备和块设备。设备号分为主设备号和从设备号,最终形成设备接点。设备节点在访问字符设备和块设备的设备驱动程序时使用。通常主设备号标识设备对应的驱动程序,大多数设备是“一个主设备号对应一个驱动程序”,如:虚拟控制台和串口终端由驱动程序4管理。此设备号由内核使用,用于确定设备文件所指的设备。字符设备和块设备注册时必须先定义好设备号。

字符设备注册函数如下:

int register_chrdev(unsigned int major ,const char *name, struct file_oprations *fops);

其中 major是主设备号。

由于对网络设备驱动程序的访问不需要设备节点,它的注册函数如下:

int register_netdev(struct net_device *dev)

注册设备所用的中断。中断在现代计算机结构中有重要的地位,操作系统必须提供程序响应中断的能力。一般是把一个中断处理程序注册到系统中去。操作系统在硬件中断发生后调用驱动程序的处理程序。

注册中断所用的函数如下:

int request_irq (unsigned irq,void(*handler)(int,void*,struct pt_regs*),unsigned long flags,const char*device,void* dev_id);

其中,irq是中断向量;handler是中断处理函数;flags是中断处理中的掩码;devices是设备名;dev_id是在中断共享使用的id。

当linux不使用该设备时,就要调用清除函数void_devicie_exit ( ),它同初始化函数相对应的,主要是:

注销设备,字符设备注销函数如下:

int unregister_chrdev(unsigned int major ,const char *name, struct file_oprations *fops);

注销中断,注销中断所用的函数如下:

int free_irq (unsigned irq,void(*handler)(int,void*,struct pt_regs*),unsigned long flags,const char*device,void* dev_id);

释放资源,模块初始化和清除函数采用module_init(device_init),module_exit(device_exit)形式

编写服务子程序

中断服务子程序,又称为驱动程序的下半部分。在Linux系统中。并不是直接从中断向量表中调用设备驱动程序的中断服务子程序,而是由Linux系统来接收硬件中断,再由系统调用中断服务子程序。中断可以产生在任何一个进程运行的时候,因此在中断服务程序被调用的时候。不能依赖于任何进程的状态,也就不能调用任何与进程运行环境相关的函数。因为设备驱动程序一般支持同一类型的若干设备,所以一般在系统调用中断服务程序的时候,都带有一个或多个参数,以唯一标识请求服务的设备。

设备驱动程序的使用

直接将驱动程序编译进linux内核

将设备驱动程序复制到 linux/drivers相关的子目录下,比如字符设备驱动程序 就放在linux/drivers/char下。

修改linux/drivers相关的子目录的Makefile,如obj-$(config_dev_driver) +=dev_driver.o,这样在编译内核时将会编译dev_driver.c,生成 dev_driver.o.

对内核进行重新编译时,进行相关的配置,比如要使用AT91RM9200的UART,就要如下配置:

Character devices -》 Serial drivers -》AT91RM9200 serial port support

将驱动程序编译成驱动模块,在设备驱动程序中有两个重要函数:

module_init(dev_init),module_exit(dev_exit)

利用相应的交叉编译器以及编译命令将驱动程序dev_driver.c编译成dev_driver.o 这样的动态驱动模块。利用insmod命令给系统安装驱动模块,如果在/dev目录下没有相应的设备文件,就可以使用mknod创建一个设备文件。利用 rmmod命令卸载驱动模块,设备文件的删除可以用rm命令。

结语

设备驱动程序的开发是在Linux环境中最复杂的编程任务之一 。它需要和硬件打交道,容易引起系统崩溃,而且很难调试。掌握设备驱动程序的开发技术,将使得开发嵌入式Linux的系统更为迅速和有效。

相关推荐

Linux两种光驱自动挂载的方法

环境:CentOS6.4西昆云服务器方式一修改fstab文件/etc/fstab是系统保存文件系统信息?静态文件,每一行描述一个文件系统;系统每次启动会读取此文件信息以确定需要挂载哪些文件系统。参...

linux系统运维,挂载和分区概念太难?在虚机下操作一次全掌握

虚拟机的好处就是可以模拟和学习生产环境的一切操作,假如我们还不熟悉磁盘操作,那先在虚机环境下多操作几次。这次来练习下硬盘扩容操作。虚拟机环境:centos8vm11linux设备命名规则在linux中...

Linux 挂载 NFS 外部存储 (mount 和 /etc/fstab)

mount:手工挂载,下次重启需再重新挂载,操作命令:mount-tnfs-ooptionsserver:/remote/export/local/directory上面命令中,本地目录...

在Linux中如何设置自动挂载特定文件系统(示例)

Linux...

Linux环境中的绑定挂载(bind mount)

简介:Linux中的mount命令是一个特殊的指令,主要用于挂载文件目录。而绑定挂载(bindmount)命令更为特别。mount的bind选项将第一个目录克隆到第二个。一个目录中的改变将会在...

Linux挂载CIFS共享 临时挂载 1. 首先

如何解决服务器存储空间不足的问题?大家好,欢迎回来。在上一期视频中,我为大家介绍了如何利用Linux挂载来扩容服务器存储空间。这一期视频,我将以Linux为例,教大家如何进行扩容。群辉使用的是Linu...

Linux 硬盘挂载(服务器重启自动挂载)

1、先查看目前机器上有几块硬盘,及已挂载磁盘:fdisk-l能够查看到当前主机上已连接上的磁盘,以及已经分割的磁盘分区。(下面以/dev/vdb磁盘进行分区、挂载为例,挂载点设置为/data)df...

linux 挂载磁盘

在Linux中挂载硬盘的步骤如下:...

笨小猪教您Linux磁盘挂载

本教程针对Linux系统比较熟悉或者想学习Linux基础的用户朋友,本教程操作起来比较傻瓜式,跟着步骤就会操作,本文使用的工具是XShell同时多多注意空格(文中会有提示)。【问答】什么是磁盘挂载?答...

Linux 磁盘挂载和docker安装命令

本篇给大家介绍Linux磁盘挂载和docker安装的相关内容,Linux服务器的操作是一个手熟的过程,一些不常用的命令隔断时间就忘记了,熟话说好记性不如烂笔头,还需在平时的工作中多练习记录。...

Linux设置开机自动挂载分区

有时候,我们在安装完Linux系统之后,可能在使用过程中添加硬盘或者分区进行使用,这时候就需要手动把磁盘分区挂载到某个路径,但是开机之后就会消失,需要重新挂载,非常麻烦,那么我们应该如何设置开机自动挂...

在linux挂载一个新硬盘的完整步骤

以下是在Linux中挂载新原始磁盘的完整步骤,包括分区、创建文件系统以及使用UUID在/etc/fstab中启动时挂载磁盘:将新的原始磁盘连接到Linux系统并打开电源。运行以下命令,...

Linux系统如何挂载exFAT分区

简介:Linux系统中不能像Windows系统那样自动识别加载新设备,需要手动识别,手动加载。Linux中一切皆文件。文件通过一个很大的文件树来组织,文件树的根目录是:/,从根目开始录逐级展开。这些文...

Linux系统挂载硬盘

fdisk-l查看可挂载的磁盘都有哪些df-h查看已经挂载的磁盘...

WSL2发布,如何在Win10中挂载Linux文件系统

WSL2是最新版本的架构,它为Windows子系统提供支持,使其能够在Windows上运行ELF64Linux二进制文件。通过最近的更新,它允许使用Linux文件系统访问存储在硬盘中的文件。如果你...

取消回复欢迎 发表评论: