【驱动】01.相关基础

【嵌入式八股】一、语言篇https://www.nowcoder.com/creation/manager/columnDetail/mwQPeM

【嵌入式八股】二、计算机基础篇https://www.nowcoder.com/creation/manager/columnDetail/Mg5Lym

【嵌入式八股】三、硬件篇https://www.nowcoder.com/creation/manager/columnDetail/MRVDlM

【嵌入式八股】四、嵌入式Linux篇(本专栏)https://www.nowcoder.com/creation/manager/columnDetail/MQ2bb0

Linux内核驱动

要从各个系统的总体框架,硬件原理,驱动层,应用层来入手学习

linux内核和驱动编程的几个面试提问,你能回答几个?_哔哩哔哩_bilibili

linux内核和驱动编程的几个提问---部分答案_哔哩哔哩_bilibili

性能优化总结_哔哩哔哩_bilibili

整体

01.某个Linux驱动开发的流程?
  1. 了解硬件:首先,你需要详细了解你要开发驱动程序的硬件设备,包括其规格、接口、工作原理等信息。
  2. 安装开发环境:在Linux系统上安装开发驱动所需的工具和编译器,通常使用GCC工具链。
  3. 查找现有驱动:在Linux内核中查找是否已经存在类似的驱动程序,如果有,可以借鉴或修改现有代码。
  4. 编写驱动程序:根据硬件的规格和Linux内核的驱动模型,编写新的驱动程序。这包括初始化、数据传输、中断处理等功能。
  5. 编译驱动:使用编译器将驱动程序源代码编译成可加载的内核模块。
  6. 加载驱动:使用insmodmodprobe命令将驱动模块加载到Linux内核中。
  7. 测试驱动:编写测试应用程序或使用现有工具来测试驱动程序的功能和性能。
  8. 调试驱动:如果出现问题,使用调试工具和技术来诊断和修复驱动程序中的错误。
  9. 性能优化:优化驱动程序的性能,以确保其在各种工作负载下表现良好。
  10. 文档编写:编写文档,记录驱动程序的使用说明和相关信息,以供其他开发人员参考。
  11. 发布驱动:如果你的驱动程序是开源的,可以将其发布到适当的开源社区或仓库中,以供其他人使用和改进。
  12. 维护驱动:随着Linux内核的更新和硬件的变化,需要定期维护和更新驱动程序。
02.嵌入式常用调试方法
  • 打印(确定问题位置、可以添加打印输出函数名,行号),或者用日志的方式

  • 打开调试开关echo 10 > /proc/sys/kernel/printk

  • 打印堆栈信息,输出函数调用关系

  • 读写寄存器列表,写个dump_regs函数

  • 寄存器查验,在应用层生成文件(device sys class create),可以在/sys/kernel/debug查看

  • GDB调试、JTAG实时运行、qemu模拟运行调试、

  • 逻辑分析仪、示波器、万用表

三打印调堆,两寄列查,GJQ示逻

03.嵌入式常见优化方法
  • 启动优化,裁剪掉没必要的

  • 数据拷贝优化(使用快速拷贝算法/使用指针(比如网络框架中,增加各种协议包头,就没有频繁拷贝,而是采用修改指针的办法,还有就是内核同步机制中的读拷贝更新RCU机制,也是这样的,因为是读优先,写的时候会写在另一片内存区域,读不忙的时候直接更改指针指向就可以了))DMA方法,解放CPU。

  • 内存使用优化帧缓冲区(参考v4l2的代码,采用了状态机的办法,在不同状态下,这片内存区域由谁使用和管理,是应用层、内核层还是硬件使用)。环形缓冲区 生产者消费者问题。

  • 优化进程启动速度,减少加载的动态库的数量,优化加载动态库时的搜索路径,进程改为线程

  • 优化代码:if表达式,从左到右对表达式求值。

  • 内存操作的优化:尽量使用占用内存少的算法,利用流水线内存存取与计算并行的特点,组合内存访问与计算

  • 调整进程的优先级

启拷使动码

内核模块

04.Linux中引入模块机制有什么好处?

Linux是宏内核操作系统的典型代表,所有内核功能都整体编译到一起,优点是效率高,缺点修改一下很麻烦。所以引入内核模块。

  • 灵活,缩短模块的开发周期,因为模块的安装和卸载都很方便。编译成模块.ko,放在应用层,用的时候插入内核,不要的时候卸载。更新不用重新修改编译内核源码。
  • 节省空间,通用的功能放进内核,多出来的不同版本的特定功能就可以放进内核模块,不用的可以不编译。(也可以用设备树)
  • 安全性好,模块有问题不会影响内核其他部分。
  • 应用程序在退出时,可以不管资源的释放或者其他的清除工作,而把这些任务交给模块退出函数(exit)。
05.内核模块三要素

module_init(led_init); //模块加载入口声明(入口)

module_exit(led_exit); //模块卸载入口声明(出口)

MODULE_LICENSE("GPL"); //模块免费开源声明(许可证)

06.module_init函数底层实现:orange:

module_init 底层实现原理-CSDN博客

module_init 其实是一个宏,它的作用是:告诉内核,该驱动程序的入口函数地址

实际上驱动的加载分为两种:静态加载、动态加载

静态加载就是把驱动程序直接编译到内核里,系统启动后可以直接调用。静态加载的缺点是调试起来比较麻烦,每次修改一个地方都要重新编译下载内核,效率较低。

动态加载利用了Linux的module特性,可以在系统启动后用insmod命令把驱动程序(.ko文件)加载上去,在不需要的时候用rmmod命令来卸载。

07.驱动程序入口函数的_ init、_ exit起什么作用?

定义为某种段属性,比如"_ section(.init.text)"、 "_section(.exit.text)"

入口函数只用一次,用完后可以释放它所占据的空间

驱动被编进内核的话,出口函数就永远不会被调用

所以入口、出口函数可以放入某个段,以后可以释放些个段

08.编译的两种方法:heart:
  • 编译成模块

固定的makefile,只需修改Linux源码路径,交叉编译路径

  • 编译进内核

放到内核的驱动目录下、写个Kconfig、再make menuconfig中对应选上生成.config配置文件(make的时候就会根据.config编译进去了)make之前写个makefile,并修改上一级makefile。然后make,生成.bin文件,做成镜像。

09.常用的驱动模块开发指令
  1. make:使用 Makefile 编译模块。如果 Makefile 配置正确,该命令将生成模块的 .ko 文件。
  2. make clean:清除模块的目标文件、中间文件和其他临时文件。
  3. insmod:将模块插入内核。使用此命令需要超级用户权限。
  4. rmmod:从内核中移除模块。使用此命令需要超级用户权限。
  5. lsmod:列出当前加载的所有模块。
  6. modprobe:自动加载模块及其依赖项,并将其添加到内核模块列表中。
  7. modinfo:显示有关模块的信息,例如版本号、作者、描述等。
  8. dmesg:显示内核消息缓冲区的内容,可用于查找与模块相关的错误或调试信息。
10.insmod,rmmod一个驱动模块,会执行模块中的哪个函数?在设计上要注意哪些问题?:heart:

当使用 insmod 命令将一个驱动模块插入内核时,模块中的 _init 函数将会被调用。这个函数用于初始化模块并向内核注册模块所提供的设备驱动程序。

当使用 rmmod 命令从内核中移除一个驱动模块时,模块中的 _exit 函数将会被调用。这个函数用于清理和卸载模块。

要注意的就是,尽量使在 init函数中出现的资源申请及使用,都要有对应的释放操作在exit中,即init申请,eixt释放。

11.驱动卸载异常可能是由什么原因引起的?
  1. 驱动程序中存在缺陷,导致无法正确地卸载。
  2. 与驱动程序相关的其他进程或服务正在运行,阻止了驱动程序的卸载。
  3. 驱动程序未正确注册或未正确初始化,导致卸载时出现错误。
  4. 与驱动程序相关的硬件设备或其他软件组件出现故障或异常,导致无法正确卸载。
  5. 驱动程序未正确处理信号或中断,导致出现异常。
  6. 系统内存或其他资源不足,导致卸载时出现错误。
12.Linux系统下.o .ko是什么文件?.a .so是什么文件?

.o 是目标文件

.o是Object File的缩写,是编译器生成的中间文件,包含目标文件的代码和数据信息,但未被链接成可执行文件。.o文件包含二进制代码、数据和符号表等信息,用于生成可执行文件或链接成静态库。

.ko是可动态安装卸载的驱动文件

.ko是Kernel Object的缩写,是Linux内核模块的二进制文件格式,用于向内核添加或卸载功能驱动。.ko文件是一种动态加载的内核模块,可以在系统运行时加载和卸载,以扩展或修改内核功能。

.a 是静态库

.a是Archive的缩写,是静态库文件,也称为静态链接库。.a文件包含多个目标文件的代码和数据,以及符号表等信息,通过静态链接可以将库文件中的目标文件和应用程序一起链接成一个可执行文件。

.so是动态链接库,类似于Windows的.dll

.so是Shared Object的缩写,是动态链接库文件,也称为共享库。.so文件包含共享代码和数据,可以被多个进程共享。在程序运行时,操作系统会将共享库映射到内存中,以供进程调用。

字符设备

设备驱动

13.设备驱动的分类

字符设备有哪些?和块设备有什么区别?

(按共性分类方

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

【嵌入式八股】嵌入式Linux 文章被收录于专栏

查阅整理上千份嵌入式面经,将相关资料汇集于此,主要包括: 0.简历面试 1.语言篇 2.计算机基础 3.硬件篇 4.嵌入式Linux【本专栏】 (建议PC端查看)

全部评论

相关推荐

实习8个月后 我成了正式工(团的日常实习是没有转正的,那段时间实习的同时备战秋招)❤️ 职场感受大三五月原计划是找一份互联网的暑期实习,当时就很想来美团(不过一想当时的简历也是白扯),后来机缘巧合和朋友到了企模的全国总决赛,就去徐州参加比赛了,也就错过了暑期实习的机会。不过比赛拿了国奖。回来之后也是各种比赛的准备,答辩把原来应该的暑期实习推迟到了七月,当时一共投了两家公司:美团和快手,说来也巧,快手和美团的一面、二面还有录用通知都是在同一天,当时也是没有纠结选择来到了美团(看来冥冥之中自有天意)👨🏻‍💻 工作环境7.10日入职美团,至今已经六个月的时间,其中有四个月我都在一边实习一边准备秋招(崩溃的笔试之后崩溃的等消息,等消息之后崩溃的面试),当时我的mentor还有我们部门的同事们都帮了我好多,带着我做项目,指导我修改简历,帮助我准备面试指出我的不足(功不可没!秋招的时间线来到末尾,当时收到了京东、字节的面试,但是都有很纠结的地方,期间我一直在美团争取面试机会,最终在差点签一个做保本前收到了美团的面试(和hr说明我的情况后很快帮我安排我的面试),面试的过程也十分的顺利,最后在收到offer的当天晚上我就联系了导员第二天去取三方。不给团子反悔的机会。就我自身情况而言还是很推荐大家来团滴~团对于应届生的锻炼还是很好的,最好的是遇到了很好的 mentor和同事们!而且美团的员工文化方面做的也很好!盲盒、大袋鼠和各种周边都超级好看! #美团求职进展汇总# #牛客创作赏金赛# #想实习转正,又想准备秋招,我该怎么办# #如果实习可以转正,你会不会放弃秋招# #美团工作体验# #美团校招#
点赞 评论 收藏
分享
FETCH API是一种用于进行网络请求的新的原生JavaScript API,它提供了一种更简单和现代化的方式来发送和接收数据。相比之下,XMLHttpRequest(XHR)是一种较旧的用于进行网络请求的原生JavaScript API。一些FETCH API与XMLHttpRequest之间的主要区别包括:https://www.nowcoder.com/issue/tutorial?zhuanlanId=Mg58Em&uuid=2d6077ad79aa408fb541e64c9f6e1ddf语法的不同:FETCH API使用基于Promise的新语法,使其更易读和使用。而XMLHttpRequest使用传统的回调函数方式。处理响应类型:FETCH API提供了更简单的方法来处理各种不同类型的响应,如JSON、文本、blob等。而在XMLHttpRequest中,需要手动设置responseType属性来处理不同的响应类型。跨域请求:使用FETCH API进行跨域请求更简单,因为默认情况下它会处理跨域资源共享(CORS)。而XMLHttpRequest需要通过设置适当的请求头和服务器响应来处理跨域请求。取消请求:FETCH API提供了一个AbortController来取消请求的能力,而在XMLHttpRequest中取消请求相对复杂。上传和下载进度:FETCH API提供了更简便的方式来获取请求的上传和下载进度,而在XMLHttpRequest中需要手动设置事件处理程序来追踪进度。总体而言,FETCH API提供了一种更加简单和现代化的方式来进行网络请求,并具有更多的灵活性和易用性。不过,XMLHttpRequest仍然是广泛使用的技术,特别是在对较旧的浏览器提供支持时。
点赞 评论 收藏
分享
评论
1
15
分享
牛客网
牛客企业服务