驱动面试题

1.驱动是什么?

驱动是一段控制设备的代码,在Linux中运行在内核空间。主要作用是上提供接口,向下控制硬件。

Linux驱动分为字符设备驱动、块设备驱动、网络设备驱动

Linux字符设备驱动遵循内核模块开发方式,入口、出口、许可证

Linux字符设备驱动需要将 物理地址映射成虚拟地址后才能操作设备相关寄存器

2.你对linux下一切皆文件的理解

“一切皆文件是指在Linux系统中”所有的设备、文件、目录等系统资源都可以被看作是一个文件,且都被组织成了一个以根目录为起点的层次结构,这种设计的好处在于,可以使用同一套文件系统调用来操作这些不同类型的资源,简化了系统的设计和管理。

例如:对于一个设备文件,可以使用文件系统调用来读写设备数据。对于一个目录,也可以使用文件系统调用来遍历其中的文件和子目录。这种一致的接口设计使得linux系统更加灵活和易于管理。

3.linux为什么要分为内核层与应用层?

Linux操作系统分为内核层和应用层的主要原因是为了提高系统的稳定性和可维护性。
内核层是操作系统的核心,它负责管理系统的各种资源,包括硬件资源(如CPU、内存、硬盘等)和软件资源(如进程、线程、文件系统等)。
内核层运行在最高的特权级别下,具有访问系统资源的最高权限。因此,内核层的代码必须经过严格的测试和验证,确保其稳定性和安全性。
应用层是建立在内核层之上的,它包括各种应用程序和工具。应用层的代码通常由第三方开发者编写,因此其质量和可靠性难以保证。
将应用程序与内核层分离,可以使操作系统更容易维护和更新。同时,如果一个应用程序崩溃或出现问题,它不会影响整个系统的稳定性。

除了提高系统稳定性和可维护性之外,将Linux操作系统分为内核层和应用层还具有以下优点:
可扩展性:通过将应用程序与内核层分离,可以使系统更容易扩展和修改,同时保持内核的稳定性。

可移植性:将应用程序与内核层分离,使得应用程序可以在不同的Linux操作系统和不同的硬件平台上运行,提高了系统的可移植性。

安全性:内核层运行在最高的特权级别下,可以保护系统的安全性,同时应用程序的沙盒机制可以避免应用程序对系统造成安全威胁。

性能:将应用程序与内核层分离,可以使系统更高效地运行,提高系统的性能。

将Linux操作系统分为内核层和应用层,不仅可以提高系统的稳定性和可维护性,还可以提高系统的可扩展性、可移植性、安全性和性能

4.linux系统为什么要将物理地址映射成虚拟地址?

Linux将物理地址映射成虚拟地址的主要原因是为了提高系统的灵活性、可移植性和安全性。
物理地址是指系统中实际的内存地址,而虚拟地址是指应用程序看到的内存地址。
在Linux操作系统中,应用程序只能访问虚拟地址,而不直接访问物理地址。
这是因为物理地址在不同的硬件平台和不同的操作系统上可能是不同的,
将物理地址映射成虚拟地址可以使应用程序对硬件和操作系统的差异保持透明。
另外,将物理地址映射成虚拟地址还可以提高系统的安全性。通过虚拟地址的映射和管理,操作系统可以隔离不同应用程序的内存空间,
防止应用程序之间相互干扰或者恶意访问彼此的内存空间,提高了系统的安全性。
此外,将物理地址映射成虚拟地址还可以提高系统的灵活性。操作系统可以将不同的虚拟地址映射到相同的物理地址上,
或者将相同的虚拟地址映射到不同的物理地址上,从而更有效地利用系统的内存资源,提高了系统的灵活性和可扩展性。
将物理地址映射成虚拟地址是Linux操作系统的一个重要特性,它可以提高系统的灵活性、可移植性和安全性,使系统更容易维护和管理。

除了提高系统的灵活性、可移植性和安全性之外,将物理地址映射成虚拟地址还具有以下优点:
内存管理:操作系统可以通过虚拟地址的映射和管理来优化内存的使用,
例如实现内存共享、虚拟内存、内存保护等功能,提高系统的性能和安全性。

调试:将物理地址映射成虚拟地址可以使调试工作更加方便和有效,因为开发人员可以通过虚拟地址来定位和调试应用程序中的内存问题,
    而不必考虑物理地址和硬件差异的问题。

兼容性:将物理地址映射成虚拟地址可以使不同的应用程序在同一台计算机上运行,或者在不同的计算机上运行,
    而不必考虑硬件和操作系统的差异。

将物理地址映射成虚拟地址是Linux操作系统的一个重要特性,它不仅可以提高系统的灵活性、可移植性和安全性,
还可以优化内存管理、方便调试和提高系统的兼容性。

5.什么是内部编译、什么是外部编译?

在Linux内核中,内部编译和外部编译的概念与一般编译器中的概念类似,但有一些特殊的区别。
内部编译(也称为静态编译)是指将内核模块编译进内核中,生成一个包含所有必要信息的内核镜像的过程。
    在内部编译的过程中,编译器会将内核模块的代码和符号链接到内核中,生成一个包含所有内核和模块的可执行文件。
    这个可执行文件可以直接运行在硬件上,而不需要依赖于外部模块。

    
外部编译(也称为动态编译)是指将内核模块编译成一个单独的目标文件,然后在运行时通过内核的模块加载器加载到内核中。
    在外部编译的过程中,编译器会生成一个包含未解决的符号的目标文件,这些符号将在运行时通过模块加载器解决。
    在外部编译的过程中,内核和模块是分开的,需要在运行时动态加载模块。

通常来说,在Linux内核中使用内部编译的优点是内核镜像包含了所有的模块,可以在系统启动时一次性加载,
避免了模块加载和符号解析的时间。但内核镜像的大小也会相应增加。使用外部编译的优点是可以根据需要动态加载和卸载模块,
减少内核镜像的大小,但是在运行时需要进行模块加载和符号解析,可能会对系统性能造成一定影响。

总之,内部编译和外部编译的选择取决于具体的需求和应用场景,在Linux内核中也需要根据实际情况选择不同的编译方式。

6.新拿到的内核如何生成导出符号表?

生成Linux内核的导出符号表需要在内核源代码目录下执行以下步骤:
修改内核配置,确保内核支持导出符号表。可以通过 
make menuconfig 命令或者修改 .config 文件来修改内核配置,具体的选项是 CONFIG_KALLSYMS 和 CONFIG_KALLSYMS_ALL,
需要将它们的值设置为 y 或者 m。
重新编译内核,并使用 make modules 命令生成内核模块。
进入内核源代码目录下的 scripts 目录,执行以下命令生成符号表:
    $ make export-symvers
这个命令会在当前目录下生成一个名为 Module.symvers 的文件,包含了内核中所有导出的符号。
注意:如果内核中有使用 EXPORT_SYMBOL_GPL 宏定义导出符号,那么在生成符号表时需要加上 KBUILD_SIGN_PIN 环境变量:
    $ make export-symvers KBUILD_SIGN_PIN=1
生成的符号表可以用于内核模块的编译和加载,可以通过编译时的 
-D 选项或者运行时的 
/proc/kallsyms文件来获取符号表中的符号信息。

7.导出符号表的作用是什么?

在Linux内核中,导出符号表是一种机制,用于将一些内核中的函数、变量、结构体等标记为可导出符号,
以便内核模块或其他内核代码可以使用它们。导出符号表中包含了内核中所有的导出符号信息,包括符号名称、地址、大小等。
导出符号表的作用主要有以下几点:
    提供给内核模块使用:
        内核模块是一种动态加载的内核代码,可以在运行时插入到内核中。
        内核模块需要使用一些内核中的函数、变量或者其他符号,但是这些符号通常是内部符号,无法被模块访问。
        通过将这些符号标记为导出符号,内核模块就可以使用它们了。

    简化内核模块的编写:
        内核模块需要使用的符号很多,如果没有导出符号表,内核模块需要自己去查找这些符号的地址,编写代码就会非常繁琐和复杂。
        通过使用导出符号表,内核模块可以直接使用内核中的符号,编写代码就会更加简单和清晰。

    内核调试和分析:
        内核开发人员可以使用导出符号表来调试和分析内核代码。导出符号表中包含了内核中所有的符号信息,
        可以方便地定位问题和调试内核代码。

总之,导出符号表是一种非常重要的内核机制,它为内核模块提供了一种简单、清晰的访问内核符号的方式,
同时也方便了内核开发人员的调试和分析工作。

8.简述你对内核模块的理解?

在Linux驱动模块中,入口、出口和许可证都是重要的元素。
入口函数:
    入口函数是Linux驱动模块的启动函数,也被称为模块初始化函数。当驱动模块被加载时,内核会调用入口函数执行初始化工作。
    入口函数通常用于注册设备、注册文件操作等,为驱动模块提供服务接口。入口函数的函数原型为
int init_module(void)。
出口函数:
    出口函数是Linux驱动模块的关闭函数,也被称为模块卸载函数。当驱动模块被卸载时,内核会调用出口函数执行清理工作。
    出口函数通常用于注销设备、注销文件操作等,释放资源。出口函数的函数原型为
void cleanup_module(void)。
许可证:
    在Linux驱动模块中,许可证用于定义模块的开放程度。许可证可以限制模块的使用和分发,也可以放宽模块的限制。
    常见的许可证包括GPL、LGPL、BSD等。许可证不仅是对模块代码的授权,也是对模块功能的约束和限制。

在驱动模块中,入口函数和出口函数是模块的必备元素,它们实现了模块的启动和关闭过程。
许可证则是模块的授权和约束,它定义了模块的使用和分发规则。
这三个元素一起构成了Linux驱动模块的基本框架,为内核提供了丰富的功能和扩展性。

9.linux应用层与内核层如何实现通讯的?

在 Linux 操作系统中,应用层和内核层之间通信的主要方式有以下几种:
    系统调用(System Call):
        应用程序通过系统调用接口向内核发起请求,以获取操作系统提供的服务和资源。例如,open()、read()、write() 等
        系统调用就是用来访问文件系统的接口。

    文件系统(File System):
        Linux 内核将文件系统映射到虚拟文件系统(Virtual File System,VFS)中,
        通过文件系统接口(例如,open()、read()、write() 等)来管理和操作文件。应用程序可以通过文件系统接口向内核发送请求,
        以读写文件等操作。

    /proc 文件系统:
        /proc 文件系统是一个特殊的文件系统,提供了许多内核状态信息和运行时统计数据。
        应用程序可以通过读取 /proc 文件系统中的文件来获取这些信息,从而与内核通信。

    设备文件(Device Files):
        设备文件是一种特殊的文件,用于与硬件设备通信。应用程序可以通过打开和读写设备文件来与设备驱动程序通信,
        而设备驱动程序则可以将请求转发到内核进行处理。

    Netlink 套接字(Netlink Socket):
        Netlink 是一种用于内核和用户空间通信的协议,它可以通过套接字接口(Netlink Socket)来实现。
        应用程序可以通过 Netlink 套接字向内核发送消息,请求内核执行某些操作或获取某些信息。

总的来说,Linux 内核和应用程序之间的通信主要依赖于系统调用和文件系统,而在某些情况下,
还可以使用 /proc 文件系统、设备文件和 Netlink 套接字等其他方式来实现通信。

10.字符设备驱动与块设备驱动的区别?

在 Linux 操作系统中,设备驱动程序分为字符设备驱动和块设备驱动,它们的主要区别如下:
    设备访问方式:
        字符设备驱动以字符为单位进行数据传输,数据的读写是直接访问,不需要缓冲。
        而块设备驱动以块(通常是 512 字节)为单位进行数据传输,数据的读写需要通过缓冲区进行,
        因此块设备通常具有更高的性能和更好的可靠性。

    数据传输方式:
        字符设备驱动通常以流的方式传输数据,即数据是连续不间断地传输。
        而块设备驱动则通常以请求/响应(Request/Response)的方式传输数据,
        即内核向设备发送请求,设备进行响应,这种方式允许数据在缓冲区中进行处理和排序,提高了数据的传输效率。

    缓存机制:
        字符设备驱动通常不具备缓存机制,而块设备驱动则通常会使用缓存机制,
        将数据缓存在内存中,以提高磁盘访问的效率。

    设备控制:
        字符设备通常用于串行通信设备(如终端、调制解调器等),可以进行流控制和信号控制等操作。
        而块设备通常用于磁盘设备,可以进行磁盘分区、格式化等操作。

总的来说,字符设备驱动和块设备驱动在数据传输方式、缓存机制、设备控制等方面有很大的差异,
应该根据实际应用需求选择不同的驱动程序。

11、字符设备驱动实现流程(框架)

12.plarform匹配设备信息与设备驱动方式有几种?

13.用户空间如何访问内核空间

在Linux中,用户空间访问内核空间的方式主要有两种:系统调用和库函数。
系统调用:用户空间程序可以通过系统调用将控制权传递给内核空间,让内核代表用户空间执行一些特权操作。
    系统调用是一种用户空间和内核空间之间的接口,它允许用户空间程序请求内核执行某些操作,例如打开文件、读写文件、创建新进程等。
    系统调用的过程中,用户空间程序将请求的参数传递给内核,内核执行完相应的操作后,将结果返回给用户空间程序。在ARM架构中,系统调用通常通过SVC指令触发。

库函数:为了方便用户空间程序访问内核提供的功能,内核提供了一些库函数,用户空间程序可以通过调用这些库函数来访问内核空间。
    这些库函数通常由动态链接库(例如libc.so)提供,它们在用户空间中运行,但是它们的实现代码是由内核提供的。
    例如,用户空间程序可以使用libc.so库函数中的open函数打开一个文件,实际上这个函数会在内核空间中执行。

为了保护内核空间不受用户空间程序的非法访问,内核空间的地址空间通常被设置为用户空间不可访问的区域,这也是将内存划分为内核空间和用户空间的主要原因之一。
因此,用户空间程序访问内核空间时,必须通过系统调用或者库函数来进行,不能直接访问。

  • 15
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值