计算机硬件和软件驱动的关系(计算机硬件系统和软件系统的作用) -凯发k8官网

我们都知道显卡不装驱动程序显卡不能正常工作,在计算机系统中,硬件设备的操作和控制需要通过驱动程序来实现,驱动程序在操作系统和硬件设备之间起到桥梁连接的作用。本文将从为何需要安装驱动程序开始,以linux 系统中的 led 驱动为例,逐步解释驱动程序的本质,以及操作系统是如何调用到驱动程序,并展示编写 arm linux led 驱动的具体步骤和代码。

为什么硬件设备正常工作需要驱动程序?

计算机系统中存在着各种不同类型的硬件设备,例如打印机、显示器、网络接口卡等。这些设备通常由不同的制造商生产,因而其工作原理和通信协议也可能各不相同。为了实现操作系统与这些硬件设备的良好协作,需要一个中间层来处理硬件细节,提供一个标准的接口供操作系统和应用程序使用,这就是驱动程序的作用。应用程序通过操作系统调用到驱动程序,从而实现操控硬件,所以驱动程序中必然是操作硬件的具体细节代码。

驱动程序的本质

驱动程序本质上是一段软件代码,它建立了硬件设备与操作系统之间的桥梁。通过这个桥梁,操作系统可以通过通用的接口调用,而无需关心硬件设备的底层细节。驱动程序通过向操作系统提供标准的命令和函数,使得应用程序可以方便地与硬件设备进行交互。

这里我们以linux系统设备驱动为例来说明一下。

在 linux 系统中,驱动程序是内核的一部分,它们以模块的形式存在。内核模块是一种可以在运行时加载和卸载的代码,允许将驱动程序动态地添加到内核中。linux 驱动程序通常由一系列的回调函数组成,这些函数定义了驱动程序与内核之间的接口。

为什么计算机硬件需要驱动程序?操作系统和硬件之间的桥梁是谁?

驱动程序在linux系统中的位置

上图中绿色部分就是驱动程序,我们可以看到,应用程序application通过调用操作系统内核提供的系统调用接口(system call interface),系统调用通过虚拟文件系统(vfs)提供的设备文件找到对应的驱动程序模块,从而调用到驱动程序中对应的操作函数,从而实现操控硬件。

应用程序如何访问到驱动程序?

为什么计算机硬件需要驱动程序?操作系统和硬件之间的桥梁是谁?

详细open过程

这里我们以linux字符设备为例,来详细说明一下应用程序是如何访问到驱动程序的。

如上图,应用程序比如要实现打开某一个字符设备的操作,那应用程序中必须调用系统调用open函数,并提供设备文/dev/led。

1.open系统调用通过字符设备文件(/dev/led)找到inode

2.根据inode的信息创建file

3.根据inode中成员i_mode 确定设备类型 c(mknod创建inode,并将c主次设备号,文件名等信息存入到inode中)

4.根据inode中成员i_rdev 确定设备号,根据设备号可以找到 cdev结构体(内核中好多字符设备,每个字符设备对应一个cdev结构体)

5.将找到的cdev结构体指针存入 inode成员i_cdev中

6.将找到的cdev 中 成员 ops(file_operation) 地址给 file中成员f_ops

7.open 根据 file中的 f_ops找到驱动中的file_opertions,这样就可以调用其中对应的open

所以驱动是以模块的形式放入内核,然后实现file_operation中对应的这些接口来为上层应用调用到。驱动中需要实现的这些接口函数代码就是操作硬件的细节代码,细节代码和硬件相关性很大。

记住一句话:应用程序是通过主设备号对应上驱动程序的。

arm linux led 驱动程序样例

linux 应用程序通过系统调用接口与设备驱动程序进行通信。对于字符设备,常见的系统调用包括 open、write、read、ioctl、close 等。应用程序通过这些系统调用向设备驱动发出命令,实现对硬件设备的控制。

以下是一个我写的完整的可运行的led驱动代码。如果你没学过linux驱动肯定看不懂全部代码,不过没关系,我只是借用这个代码来讲解一下驱动程序到底是要写什么。

#include #include #include #include #include #include #include #include #define led_on _io('c',0)#define led_off _io('c',1)#define gpx2con 0x11000c40#define gpx2dat 0x11000c44static int led_major = 0; struct led_dev{ struct cdev led_cdev; dev_t devnum; volatile unsigned int *gpx2con; volatile unsigned int *gpx2dat;}led_dev;int led_open(struct inode * inodep, struct file *filep){ printk("led device opened !n"); return 0;}int led_close(struct inode *inodep, struct file *filep){ printk("led device closedn"); return 0;}ssize_t led_read(struct file *filep, char __user *ubuf, size_t size, loff_t *loff){ return 0;}ssize_t led_write(struct file *filep , const char __user *ubuf, size_t size, loff_t *loff){ return 0;}long led_ioctl(struct file *filep, unsigned int cmd, unsigned long arg){ switch(cmd){ case led_on: iowrite32(ioread32(led_dev.gpx2dat) | (0x1 << 7), led_dev.gpx2dat); break; case led_off: iowrite32(ioread32(led_dev.gpx2dat) & (~(0x1 << 7)), led_dev.gpx2dat); break; default: return -einval; } return 0;}struct file_operations led_ops = { .owner = this_module, .open = led_open, .release = led_close, .read = led_read, .write = led_write, .unlocked_ioctl = led_ioctl };static int led_init(void){ int result; //1.alloc device num result = alloc_chrdev_region(&(led_dev.devnum),0,1,"led"); if(result < 0){ printk("chrdev device num alloc errorn"); return result; } led_major = major(led_dev.devnum); printk("led major = %dn",led_major); //2.init cdev cdev_init(&led_dev.led_cdev,&led_ops); //3.add cdev result = cdev_add(&led_dev.led_cdev,led_dev.devnum,1); if(result < 0){ printk("cdev add errorn"); goto err1; } //4.map led register led_dev.gpx2con = ioremap(gpx2con, sizeof(int)); if(led_dev.gpx2con == null){ printk("led device gpx2con remap failed!n"); goto err2; } led_dev.gpx2dat = ioremap(gpx2dat, sizeof(int)); if(led_dev.gpx2dat == null){ printk("led device gpx2dat ioremap failed!n"); goto err3; } //5.setting gpx2_7 pin output mode iowrite32((ioread32(led_dev.gpx2con) & (~(0xf << 28))) | ((0x1 << 28)), led_dev.gpx2con); iowrite32(ioread32(led_dev.gpx2dat) & (~(0x1 << 7)), led_dev.gpx2dat); printk("led driver module init ok!n"); return 0;err3: iounmap(led_dev.gpx2con);err2: cdev_del(&led_dev.led_cdev);err1: unregister_chrdev_region(led_dev.devnum,1); return result; }static void led_exit(void){ //1.del cdev cdev_del(&led_dev.led_cdev); //2.release chrdev device num unregister_chrdev_region(led_dev.devnum,1); printk("led driver module exit!n"); }module_license("gpl");module_author("albert@gmail.com");module_description("the driver for led device");module_init(led_init);module_exit(led_exit);

重点在file_operations这个结构体,可以看到我在驱动中实现了led_open,led_close,led_write和led_ioctl五个具体操作接口,上层就是通过这个5个指针调到驱动中这五个函数。

为什么计算机硬件需要驱动程序?操作系统和硬件之间的桥梁是谁?

file_operations

具体实现led灯亮灭的代码就在led_ioctl这个函数,这个不同硬件电路具体代码不一样,

ioctl细节代码

但是可以看到其实就是操作寄存器,设置寄存器对应位高低电平就能实现灯亮灭。操作硬件就是操作寄存器这是通用底层逻辑。

我们来看一下驱动程序对应的应用层测试代码。

#include #include #include #include #include #include #define led_on _io('c',0)#define led_off _io('c',1)int main(int argc, char **argv){ int fd = open(argv[1], o_rdwr); if(-1 == fd){ printf("open device error"); return -1; } while(1){ ioctl(fd, led_on); sleep(2); ioctl(fd, led_off); sleep(2); } close(fd); return 0;}

应用层代码就是调用ioctl系统调用来实现等的2秒闪烁功能。应用层这里通过调用ioctl可以通过文件系统调到驱动程序中注册的file_operations中unlocked_ioctl指针指向的led_ioctl函数,从而实现led的亮灭。

本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。e-mail:dandanxi6@qq.com

(0)
上一篇 2024-01-26 10:40
下一篇 2024-01-27 14:15

相关推荐

  • 1、母亲节的来源 母亲节(mother's day),是一个感谢母亲的节日。现代的母亲节起源于美国,是每年5月的第二个星期日。这个节日的发起人是费城人安娜·贾维斯,这个女…

    2022-11-21
  • 新中国成立,政通人和,艺术界也迎来了她的春天,百花齐放,争奇斗艳。 那一段时期的中国钢琴界成果斐然,同时升起五颗新星,他们是傅聪、刘诗昆、顾圣婴、李名强、殷承宗;他们的出色表现引起…

    2022-12-16
  • 说到酸菜鱼呢,相信很多人都爱吃,但是如果要自己做呢,同样也可能很多人会懵逼,无从下手,其实说实话的,酸菜鱼的做法并没有你们想象的那么复杂,可谓菜入百家,就有百种做法,这期的美食教程…

    2023-12-19
  • 必须抵制。 艺人作为公众人物一言一行都影响着社会舆论,一颦一笑都会被未成年人模仿,正因如此,艺人才更应该端正自己的言行,为社会贡献正能量,做出好的榜样。 柯震东年少成名,大红大紫,…

    2022-11-26
  • 随着我国经济的不断发展和人民生活水平的提高,国内对各种农副产品的需求也在不断提高。2020年我国进口了创纪录的1亿吨大豆,有利的满足了国内食品、餐饮、养殖等行业对大豆的需求。 中国…

    2023-04-30
  • 成本法与权益法的区别一:适用范围   成本法是两头,权益法是中间。   权益法:适用情况是对合营、联营企业的长期股权投资核算,通常占股在20%〜50%。   成本法:适用情况是对能…

    2022-11-19
  • 《洛克王国》莉莉技能表图鉴最新

    洛克王国游戏中很多玩家想知道【莉莉】怎么样,宠物的资料卡,技能属性种族值等情况如何呢?下面小编就给大家带来了《洛克王国》莉莉技能表图鉴介绍,感兴趣的速来围观吧! 《洛克王国》莉莉技…

    2023-04-25
  • 前几天遇到这样一个问题: 最早的七言绝句是什么时候有的?有怎样的历史? 前言 七言绝句就是四个七言句组成的诗,简称七绝。七绝和五绝一样,有近体诗有古体诗。 我们都知道七绝在唐朝达到…

    2022-12-01
  • 出生的那一天 就是一个人冒险的起点 这世界本来就很危险 走在不归路上体验各种惊险 受一次伤就学会推诿 求安稳就别指望有所建树 做一件事 做好被骗的准备 别前怕狼后怕虎 中间还怕有一…

    用户投稿 2022-12-10
  • 万宝路香烟深受各国烟民的喜爱,但伴随万宝路发展中有一个惋惜的爱情故事。 万宝路由一个叫john穷大学生发明创造出过滤嘴,使最一开始的普通烟卷,但因为增加了过滤头后,方便了吸烟者,也…

    2022-12-16
网站地图