应用程序与库函数、内核、驱动之间的关系

来源:互联网 发布:xampp使用教程 php版本 编辑:程序博客网 时间:2024/05/16 15:41

应用程序与库函数、内核、驱动之间的关系

    应用程序、库、内核、驱动程序的关系:应用程序调用应用程序函数库完成功能、应用程序以文件形式访问各种资源、应用程序函数库、部分函数直接完成功能、部分函数通过系统调用。

   由内核完成内核处理系统调用。


   调用设备驱动程序,设备驱动直接与硬件通信。

        它们之间的关系如下图所示



    设备类型:

    常见的设备有三类:字符设备、块设备、网络设备。

    字符设备:对字符设备发出读/写请求时,实际的硬件I/O操作一般紧接着发生。

    块设备:块设备与之相反,它利用系统内存作为缓冲区。

    网络设备:网络设备是一类特殊的设备,它不像字符设备或块设备那样通过对应的设备文件节点访问,也不能直接通过read                                    write进行数据访问请求。

       

    设备号

        硬件设备以主设备号和从设备号区分。在设备管理中,除了设备类型外,内核还需要对被称为主从设备号的参数,才能唯一     标识一个设备。主设备号相同的设备使用相同的驱动程序,从设备号用于区分具体设备的实例。在/dev目录下使用ll命令(ls -l)     可以查看各个设备的设备类型、主从设备号等。cat /proc/devices可以查看系统中所有设备对应的主设备号。

 

    设备文件

        设备类型、主从设备号是内核与设备驱动程序通信时使用的,应用程序使用设备文件节点访问对应设备。Linux 2.4引入了设     备文件系统(devfs)所有的设备文件作为一个可以挂载的文件系统,每个主从设备号确定的设备都对应一个文件节点。每个设     备文件都有其文件属性(c代表字符设备或者b代表块设备),都有2个设备号:1、主设备号,用于标识驱动程序;2、从设备       号:用于标识同一驱动程序的不同硬件。设备文件的主设备号必须与设备驱动程序在登记时申请的主设备号一致。需要注意的       是,系统调用是内核与应用程序之间的接口,设备驱动程序是内核与硬件之间的接口。

 

    驱动程序与应用程序的区别

         1、应用程序以main开始,驱动程序没有main,它以一个模块初始化函数作为入口。

         2、应用程序从头到尾执行一个任务,驱动程序完成初始化之后不再运行,等待系统调用。

         3、应用程序可以使用GLIBC等标准C函数库,驱动程序不能使用标准C库。

 

    用户态与内核态

        系统运行时一般情况下,分用户态和内核态,这两种运行态下的数据互不可见的。驱动程序是内核的一部分,工作在内核       态,应用程序工作在用户态。这样就存在数据空间访问的问题:无法通过指针直接将二者的数据地址进行传递。问题的解决办法     是:系统提供一系列函数帮助完成数据空间转换:例如,get_user put_user copy_from_user copy_to_user

    等函数。

 

        Linux驱动程序功能

        驱动程序的一般功能是:对设备初始化和释放、把数据从内核传送到硬件和从硬件读取数据、读取应用程序传送给设备文件     的数据和回送应用程序请求的数据、检测和处理设备出现的错误等。




    以LED为代表:

    1.应用程序使用库提供的open函数打开代表LED的设备文件
    2.库根据open函数传入的参数执行“swi”指令,这条指令会引起CPU异常,进入内核
    3.内核的异常处理函数根据这些参数找到相应的驱动程序,返回一个文件句柄给库,进而返回给应用程序
    4.应用程序得到文件句柄后,使用库提供的write或者ioclt函数发出命令。
    5.库根据write或者ioclt函数传入的参数执行"swi"指令,这条指令会引起CPU异常,进入内核
    6.内核的异常处理函数根据这些参数调用驱动程序的相关函数,点亮LED。

    注:两次内核的异常处理是不同的,一次是返回文件句柄,一次是调用驱动程序相关函数

        库(比如glibc)给应用程序提供的open,read,write,ioctl,mmap等接口函数被称为系统调用,他们都     是设置好相关的寄存器后,执行某条指令引发异常进入内核。对于ARM架构CPU,这条指令为swi.除系统调     用接口外,库还提供其他函数,比如字符串处理函数(strcmp,strcpy),输入输出函数(printf,scanf等)、     数学库,还有应用程序的启动代码。

        在异常处理函数中,内核会根据传入的参数执行各种操作,比如根据设备文件名找到对应的驱动程       序,调用驱动程序相关函数等。

        实际上,内核和驱动程序之间并没有界限,因为驱动程序最终还是要编进内核中去的:通过静态链接     或者动态加载。

        与应用程序不同,驱动程序从来不主动运行,他是被动的:根据应用程序的要求进行初始化,根据应     用程序的要求进行读写。驱动程序加载进内核时,只是告诉内核“我在这里,我能做哪些工作”,以至       于“工作”何时开始,取决于应用程序。当然,这也不是绝对的,比如用户完全可以写一个系统时钟触发     的驱动程序,让他自动点亮LED。

        在Linux系统中,应用程序运行于“用户空间”,拥有MMU的系统能够限制应用程序的权限(比如将他     限制于某个内存块中),这样可以避免应用程序的错误导致整个系统崩溃。而驱动程序运行于“内核空       间”,他是系统“信任”的一部分,驱动程序的错误有可能导致整个系统崩溃



0 0
原创粉丝点击