创娱开源帮助中心

首页 >> 游戏资讯
应用程序中的函数如何调用到驱动里
来源:本站 作者:超级管理员 2022-08-15 18:01:00

摘要:

应用程序中的函数如何调用到驱动里?应用程序调用驱动程序?关注“技术简说”,带你一步一步学习linux内核驱动。linux操作系统用文件抽象出了这一切,文件成为了以上这些实体的编程接口。正由于此,基于linux的

应用程序中的函数如何调用到驱动里?应用程序调用驱动程序?关注“技术简说”,带你一步一步学习linux内核驱动。linux操作系统用文件抽象出了这一切,文件成为了以上这些实体的编程接口。正由于此,基于linux的编程变成了面向文件的编程,对于linux应用程序开发者而言,简直是爽的不要不要的。本文接着linux驱动开发第1讲:带你编写一个最简单的字符设备驱动,来讲述linux应用程序中的write()函数如何调用到hello驱动里的write()函数,并顺道回答上一讲最后的几个遗留问题。

应用程序中的函数如何调用到驱动里

关注“技术简报”,带你一步步学习linux内核驱动。

在linux操作系统中,一切都是文件:文件是文件,目录是文件,设备是文件,套接字是文件,管道也是文件。

Linux操作系统用文件把这一切抽象出来,文件成为这些实体的编程接口。正因为如此,基于linux的编程变成了面向文件的编程,对于linux应用开发者来说简直酷毙了,没必要。

但是,对于内核开发者来说,不一定。虽然应用层可以用open、write、read read操纵一切,但是在内核中,要真正实现这一切,需要不同的部分(或者驱动)。

然后,本文的linux驱动开发第一讲:带你编写最简单的字符设备驱动,讲述linux应用中的write()函数如何调用hello driver中的write()函数,并回答最后一讲剩下的几个问题。

首先,上图简要说明了呼叫过程:

应用层-系统调用-驱动

任何可以正常使用的函数,如果没有在你的应用中定义,都必须在C库中定义。而C库会怎么做要看情况。像一些字符处理函数,C库会实现;但是和write函数一样,C库只会做一些检查,然后陷入write系统调用,会被困在内核空间被软中断执行。

应用空间和内核空间是相互隔离的,彼此看不到对方,也无法访问对方的数据。这是为了安全。所以就write函数而言,用户空间通过系统调用进入内核空间后,内核需要copy_from_user函数将应用程序发送的数据复制到内核空间,然后内核空间才能处理这些数据。

整个过程,如上图所示,非常明显,但也存在一些问题。操作系统中的系统调用如何最终知道哪个驱动应该调用write函数?在《linux驱动开发第一讲:带你写最简单的字符设备驱动》中,我们确实看到在执行测试程序时,调用测试程序中的open、write、read函数时,分别调用hello驱动中的hello_open、hello_write、hello_read函数。这是巧合吗?

当然不是!

我们先从逻辑上解释一下这个问题。

如果我们没记错,在hello驱动程序中,定义了主设备号和辅助设备号:

在hello_init中,我们将主设备号232和这个设备号0组合成devNum。

cdev_init(gDev,gFile);建立gDev和gFile之间的逻辑关系。

cdev_add(gDev,devNum,3);建立gDev和devNum之间的逻辑关系。

其实当你打开代码看细节的时候,你会发现上面两个代码其实建立了gFile和devNum的对应关系,也就是file_operations和devNum的对应关系,也就是file_operation和主副设备号(232,0)的对应关系。

注意:在linux中,文件句柄,也就是fd,在应用层用来表示打开的文件,而struct file在内核中用来表示打开的文件,struct file_operations用来表示文件的操作。fd struct file和struct file_operations是一一对应的。这是struct file_operations的结构定义:

在前面的例子中,我们打开的文件的名称是/dev/hello,这是一个设备文件,对应的主设备号和辅助设备号分别是232和0。所以当你打开/dev/hello的时候,这个文件和hello驱动中的struct文件的对应关系已经建立,这个文件和hello驱动中的struct file_operations的对应关系也已经建立。

好了,了解了上面的背景之后,我们来看看代码。

从我们内核中写系统调用的实现部分开始读:

相关代码为:fs/read _ write.c。

注意:SYSCALL_的开头表示它是一个系统调用。

关键代码是vfs_write。那么,让我们继续跟进:

继续跟踪__vfs_write:

关键在这里,

上面提到/dev/hello和file_operations之间的关系是建立的。所以这里其实是判断hello驱动中是否定义了write函数。如果有,调用hello驱动中的write函数。

所以按照上面的路径,应用中的write成功调用了hello驱动中的write函数。因为我们驱动中的hello_write和hello_read都返回0。因此,应用程序中的写入和读取也返回0。

如果您希望测试程序中的写和读返回非零值,只需将驱动程序中的return 0更改为任意值。你可以自己测试一下。



上一篇:《阴阳师》×TV动画《鬼灭之刃》联动第三弹即将开启! 下一篇:魔兽世界冬幕节任务奖励(怀旧服节日活动—冬幕节攻略)