LinuxDown

LinuxDown.com
Linux系统下载网——精选每一篇高品质的技术干货
  1. 首页
  2. 开源快讯
  3. 正文

Linuxdevicedriver的概念系统调用是操作系统内核和应用程序

2023年6月23日 431点热度

1

Linuxdevicedriver的概念

系统调用是操作系统内核和应用程序之间的插口,设备驱动程序是操作系统内核和机器硬件之间的插口。设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部份,它完成以下的功能:

1、对设备初始化和释放;

2、把数据从内核传送到硬件和从硬件读取数据;

3、读取应用程序传送给设备文件的数据和回送应用程序恳求的数据;

4、检测和处理设备出现的错误。

在linux操作系统下有三类主要的设备文件类型,一是字符设备,二是块设备,三是网路设备。字符设备和块设备的主要区别是:在对字符设备发出读/写恳求时,实际的硬件I/O通常就紧接着发生了,块设备则不然,它借助一块系统显存作缓冲区,当用户进程对设备恳求能满足用户的要求,就返回恳求的数据,若果不能,就调用恳求函数来进行实际的I/O操作。块设备是主要针对c盘等慢速设备设计的,以免花费过多的CPU时间来等待。

早已提及,用户进程是通过设备文件来与实际的硬件打交道。每位设备文件都都有其文件属性(c/b),表示是字符设备还是块设备?另外每位文件都有两个设备号,第一个是主设备号,标示驱动程序,第二个是从设备号,标示使用同一个设备驱动程序的不同的硬件设备,例如有两个软驱,就可以用从设备号来分辨她们。设备文件的的主设备号必须与设备驱动程序在登记时申请的主设备号一致,否则用户进程将难以访问到驱动程序。

最后必须提及的是,在用户进程调用驱动程序时,系统步入核态度,这时不再是抢鲜式调度。也就是说,系统必须在你的驱动程序的子函数返回后才会进行其他的工作。假如你的驱动程序深陷死循环,不幸的是你只有重新启动机器了,之后就是漫长的fsck。

2

案例分析

我们来写一个最简单的字符设备驱动程序。其实它哪些也不做,而且通过它可以了解Linux的设备驱动程序的工作原理。把下边的C代码输入机器,你都会获得一个真正的设备驱动程序。

因为用户进程是通过设备文件同硬件打交道,对设备文件的操作方法不外乎就是一些系统调用,如open,read,write,close…,注意,不是fopenlinux驱动编程,fread,然而怎样把系统调用和驱动程序关联上去呢?这须要了解一个十分关键的数据结构:

struct file_operations {int (*seek) (struct inode * ,struct file *, off_t ,int); int (*read) (struct inode * ,struct file *, char ,int); int (*write) (struct inode * ,struct file *, off_t ,int); int (*readdir) (struct inode * ,struct file *, struct dirent * ,int); int (*select) (struct inode * ,struct file *, int ,select_table *); int (*ioctl) (struct inode * ,struct file *, unsined int ,unsigned long); int (*mmap) (struct inode * ,struct file *, struct vm_area_struct *); int (*open) (struct inode * ,struct file *); int (*release) (struct inode * ,struct file *); int (*fsync) (struct inode * ,struct file *); int (*fasync) (struct inode * ,struct file *,int); int (*check_media_change) (struct inode * ,struct file *); int (*revalidate) (dev_t dev); }

这个结构的每一个成员的名子都对应着一个系统调用。用户进程借助系统调用在对设备文件进行例如read/write操作时,系统调用通过设备文件的主设备号找到相应的设备驱动程序,之后读取这个数据结构相应的函数表针,接着把控制权交给该函数。这是linux的设备驱动程序工作的基本原理。既然是这样,则编撰设备驱动程序的主要工作就是编撰子函数,并填充file_operations的各个域。

下边就开始写子程序。

#include  基本的类型定义#include  文件系统使用相关的头文件#include  #include  #include  unsigned int test_major = 0; static int read_test(struct inode *inode,struct file *file,char *buf,int count){ int left; 用户空间和内核空间if (verify_area(VERIFY_WRITE,buf,count) == -EFAULT ) return -EFAULT; for(left = count ; left > 0 ; left--) { __put_user(1,buf,1); buf++; } return count; }

这个函数是为read调用打算的。当调用read时,read_test()被调用,它把用户的缓冲区全部写1。buf是read调用的一个参数。它是用户进程空间的一个地址。并且在read_test被调用时,系统步入核态度。所以不能使用buf这个地址,必须用__put_user(),这是kernel提供的一个函数,用于向用户传送数据。另外还有好多类似功能的函数。请参考,在向用户空间拷贝数据之前,必须验证buf是否可用。这就用到函数verify_area。为了验证BUF是否可以用。

static int write_test(struct inode *inode,struct file *file,const char *buf,int count) { return count; }static int open_test(struct inode *inode,struct file *file ) {MOD_INC_USE_COUNT; 模块计数加以,表示当前内核有个设备加载内核当中去return 0; } static void release_test(struct inode *inode,struct file *file ) { MOD_DEC_USE_COUNT; }

这几个函数都是空操作。实际调用发生时哪些也不做,她们仅仅为下边的结构提供函数表针。

struct file_operations test_fops = {? read_test, write_test, open_test, release_test, };

设备驱动程序的主体可以说是写好了。如今要把驱动程序嵌入内核。驱动程序可以根据两种形式编译。一种是编译进kernel,另一种是编译成模块(modules),假如编译进内核的话,会降低内核的大小linux服务器系统,还要改动内核的源文件,但是不能动态的卸载,不利于调试,所以推荐使用模块形式。

int init_module(void) { int result; result = register_chrdev(0, "test", &test_fops); 对设备操作的整个接口if (result < 0) { printk(KERN_INFO "test: can't get major numbern"); return result; } if (test_major == 0) test_major = result; /* dynamic */ return 0; }

在用insmod命令将编译好的模块调入显存时,init_module函数被调用。在这儿,init_module只做了一件事,就是向系统的字符设备表登记了一个字符设备。register_chrdev须要三个参数,参数一是希望获得的设备号linux驱动编程,若果是零的话,系统将选择一个没有被占用的设备号返回。参数二是设备文件名,参数三拿来登记驱动程序实际执行操作的函数的表针。

假如登记成功,返回设备的主设备号,不成功,返回一个负值。

void cleanup_module(void) { unregister_chrdev(test_major,"test"); }

在用rmmod卸载模块时,cleanup_module函数被调用,它释放字符设备test在系统字符设备表中占有的表项。

一个非常简单的字符设备可以说写好了,文件名就叫test.c吧。

下边编译:

$gcc-O2-DMODULE-D__KERNEL__-ctest.c–c表示输出拟定名,手动生成.o文件

得到文件test.o就是一个设备驱动程序。

puppy linux 编程_linux驱动编程_linux 驱动编程 class

假如设备驱动程序有多个文件,把每位文件按前面的命令行编译,之后

ld?-r?file1.o?file2.o?-o?modulename。

驱动程序早已编译好了,如今把它安装到系统中去。

$insmod?–f?test.o

假如安装成功,在/proc/devices文件中就可以看见设备testlinux操作系统下载,并可以看见它的主设备号。要卸载的话,运行:

$rmmodtest

下一步要创建设备文件。

mknod/dev/testcmajorminor

c是指字符设备,major是主设备号,就是在/proc/devices里听到的。

用shell命令

$cat/proc/devices

就可以获得主设备号,可以把里面的命令行加入你的shellscript中去。

minor是从设备号,设置成0就可以了。

我们如今可以通过设备文件来访问我们的驱动程序。写一个小小的测试程序。

#include  #include  #include  #include  main() { int testdev; int i; char buf[10]; testdev = open("/dev/test",O_RDWR);if ( testdev == -1 ) { printf("Cann't open file n"); exit(0); }read(testdev,buf,10); for (i = 0; i < 10;i++) printf("%dn",buf[i]); close(testdev); }

编译运行,瞧瞧是不是复印出全1?

以上只是一个简单的演示。真正实用的驱动程序要复杂的多,要处理如中断,DMA,I/Oport等问题。这种才是真正的难点。上述给出了一个简单的字符设备驱动编撰的框架和原理,更为复杂的编撰须要去认真研究LINUX内核的运行机制和具体的设备运行的机制等等。希望你们好好把握LINUX设备驱动程序编撰的方式。

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: 函数调用 块设备 字符 系统调用
最后更新:2023年6月23日

Linux系统下载网

每日更新,欢迎收藏♥ 不积跬步无以至千里,加油,共勉。

点赞
< 上一篇
下一篇 >

Linux系统下载网

每日更新,欢迎收藏♥
不积跬步无以至千里,加油,共勉。

最新 热点 随机
最新 热点 随机
Linux系统助你轻松查看sh文件内容 熠熠生辉的C语言Linux开发者的好书和技术参考资料 fedora win7 双系统 Fedora与Win7双系统完美融合 Windows10版本1803和更高版本重置密码18031803 yum安装PHP5.4的亲身体验系统管理员 编译流程(12、GCC、hello.s)预处理 不同操作系统中比较常见的文件系统定义是什么 快速掌握fedora终端打开技巧 Ubuntu下软件安装的几种方式,及apt工具的使用 Red Hat Linux AS下载对比 深度解析Linux网络带宽测试,揭秘速度与激情 文件路径例子及应用软件下载工具 Fedora安装Steam,一键搞定 修改root用户的密码需要注意哪些问题? Linux僵死:解决与预防 开始开发小程序的第一步,你的小程序之旅 Linux移植:地址划分与分配解析 应用软件工程师的隐形之道:驱使硬件设备行动 Linux命令与Shell脚本实践:九个重点指南 phpWeChat微信+网站开发框架功能亮点解析!安装方法
完成远程连接以后就可以安装图形化界面,配置低了会比较卡Linux系统助你轻松查看sh文件内容快速了解Linux内核版本,查看命令揭秘!SUSELinux12SP5的安装步骤及安装方法Linux部署Tomcat项目对比评测基于精简指令集计算原理建立的CPU体系结构有不同的特点和应用场景Linux操作系统:端口查进程用做ASIC芯片的EDA仿真工具来做FPGA的仿真调试ghost linux系统 备受瞩目的Ghost Linux:稳定性与性能共赢Centos7无人值守安装系统架构及工作原理启动畅行编程世界,掌握Linux Java环境LinuxCentOS7中如何安装字体库以及中文字体?Linux Find命令:简单使用正则统计次数本地Windows远程桌面连接阿里云Ubuntu16.04服务器:1linux 解压zip文件 (Linux基础知识)Linux常用的压缩命令和常见用法打造高效稳定的Linux网络应用(Linux基础知识)linuxuserdel命令是系统管理员命令解决Linux命令行中文乱码问题Linux内核下载地址,Linux之旅加速!《Linux命令大全Linuxscp命令》命令
轻松掌握Linux 64位版本查看技巧,图形界面秒懂! 解决Linux命令行中文乱码问题 开源奇迹:Linux视频编程的魅力 如何在Linux官网下载Linux镜像文件ISO?(/) Linux轻松安装:VirtualBox虚拟机指南 基于驱动理论的支持,课题实现ESM(Embedded)系统 Linux文件上传利器:rz命令端口设置 轻松掌握Linux系统基本命令大全,10个常用命令助你驾驭命令行 北京周末嵌入式Linux培训,轻松掌握开发技能! Linux基础教程:cp命令演示16个有用的cp示例 Linux查看GTK版本的实用技巧 创建用户的时候指定分组是怎样的体验? 阿里云官方公共Linux系统镜像不会安装图形化桌面组件 WPS Office Linux:办公软件评测对比 简便下载Linux,畅享网易镜像站! 文件系统数据权限设计是一项重要的任务,确保数据安全 一直不太明白Linux系统的磁盘分区与目录结构之间的关系 Linux操作系统的安装方法(42页珍藏版) 如何快速地下载并学习Linux的经验和技巧? Linux轻松驾驭 DOS,命令完美融合
标签聚合
软件 安装 文件 内核 应用 linux系统 linux服务器 命令 电脑 操作
书籍
课程
技术群
技术干货大合集↓
  • 2023年9月 / 118篇
  • 2023年8月 / 122篇
  • 2023年7月 / 122篇
  • 2023年6月 / 119篇
  • 2023年5月 / 123篇
  • 2023年4月 / 113篇
  • 2023年3月 / 265篇
友情链接:

Linux书籍 | Linux命令 | Linux系统 | RHCE红帽认证 | Linux软件 | Linux教程 | CentOS系统 | Linux内核 | Linux服务器 | Linux大神 | IT资源

COPYRIGHT © 2023 LinuxDown.com ALL RIGHTS RESERVED.

京ICP备14023444号-2