嵌入式面试高频(实战场景2)

此部分不只包含面经内容,均是实战类型不必全文背诵,有思路即可

后续收录于专栏:嵌入式/C++面试八股文

实战场景2

1 linux中内核空间及用户空间的区别?用户空间与内核通信方式有哪些?⭐⭐⭐⭐⭐

Linux 中内核空间和用户空间存在多方面区别,用户空间与内核的通信方式也多种多样,具体如下:

内核空间与用户空间的区别

  • 权限级别:内核空间具有最高权限,能访问所有硬件资源和执行特权指令。用户空间权限较低,只能访问受限的资源,以防止用户程序破坏系统
  • 功能职责:内核空间负责管理硬件、调度进程、分配内存等核心任务。用户空间用于运行用户程序和应用,通过系统调用请求内核服务。
  • 内存布局:内核空间占用特定的内存区域,有自己的内存管理机制,存储内核代码和数据结构。用户空间的每个进程都有独立的虚拟地址空间,包含代码、数据、堆、栈等区域。

用户空间与内核的通信方式

  • 系统调用:用户程序通过系统调用接口进入内核空间,请求内核提供服务,如文件读写、进程创建等。
  • 信号:内核可以向用户进程发送信号,通知进程发生了特定事件,如进程终止、定时器到期等,用户进程可以通过信号处理函数来响应信号。
  • 共享内存:内核和用户空间可以通过共享内存区域进行数据交互,需要使用同步机制来确保数据的一致性和完整性。
  • 管道和消息队列:管道用于具有亲缘关系的进程间通信,消息队列可用于不同进程间按消息进行数据传递,内核在其中负责管理和维护通信机制。

2 字符设备和块设备的区别,请分别列举一些实际的设备说出它们是属于哪一类设备⭐⭐⭐⭐

区别

数据传输方式

  • 字符设备:以字符为单位进行数据传输,数据的读写是按顺序逐个字符进行的,通常不支持随机访问。
  • 块设备:以数据块为单位进行数据传输,支持随机访问,可以直接访问设备上的任意数据块。

访问速度

  • 字符设备:访问速度相对较慢,常用于低速的、对数据传输实时性要求不高的场景。
  • 块设备:访问速度相对较快,适合大量数据的快速读写操作。

数据缓存

  • 字符设备:一般不使用缓存或者只有很小的缓存,因为其数据传输通常是实时的、顺序的。
  • 块设备:通常有较大的缓存,以提高数据的读写性能,减少对物理设备的访问次数。

常见设备举例

  • 字符设备:键盘、鼠标、串口设备、打印机等。例如键盘,用户按下按键时,字符会逐个被系统接收,系统按字符流的方式处理输入信息。
  • 块设备:硬盘、固态硬盘、U 盘、光盘等。以硬盘为例,操作系统可以直接读取或写入硬盘上的任意一个数据块,实现快速的数据存储和检索。

3 linux中系统调用过程?如应用程序中read()在linux中执行过程即从用户空间到内核空间?⭐⭐⭐⭐

Linux 中系统调用read()的执行过程,即从用户空间到内核空间的过程如下:

  • 用户空间发起调用:应用程序在用户空间中执行到read()函数时,会将所需的参数(如文件描述符、缓冲区指针、读取字节数等)按照规定的调用约定放入寄存器或栈中,准备发起系统调用。
  • 陷入内核:通过执行特定的指令(如 x86 架构中的int 0x80或sysenter指令),产生一个软件中断,使 CPU 从用户态切换到内核态,程序的执行流跳转到内核中系统调用的入口点。
  • 内核处理:内核根据系统调用号(read()有对应的系统调用号)在系统调用表中找到read()对应的内核函数sys_read(),并开始执行。sys_read()会对文件描述符进行合法性检查等操作,然后根据文件类型等调用相应的驱动程序的读函数从设备或文件中读取数据到指定的缓冲区。
  • 返回用户空间:数据读取完成后,内核将读取到的字节数等结果放入指定的寄存器中,通过执行特定指令完成从内核态到用户态的切换,将控制权交还给应用程序,应用程序继续执行read()调用后的代码,使用读取到的数据。

4 查看驱动模块中打印信息应该使用什么命令?如何查看内核中已有的字符设备的信息?如何查看正在使用的有哪些中断号?⭐⭐⭐

查看驱动模块打印信息

  • 可使用dmesg命令,它能显示内核环形缓冲区的信息,驱动模块加载、运行时打印的信息会记录在内核日志里,执行dmesg即可查看。若想查看最新信息,可加-T参数显示时间戳,用-H以人类可读格式输出。

查看内核中已有字符设备信息

  • 使用cat /proc/devices命令,它会列出内核中已注册的字符设备和块设备及其对应的主设备号。字符设备部分能看到设备名和主设备号,便于了解系统里字符设备的注册情况。

查看正在使用的中断号

  • 用cat /proc/interrupts命令,该文件记录了系统中每个中断号对应的使用情况,包括中断类型、使用该中断的设备等信息,能清晰了解哪些中断号正在被使用。

5 copy_to_user()和copy_from_user()主要用于实现什么功能?一般用于file_operations结构的哪些函数里面?⭐⭐⭐⭐

主要功能

  • copy_to_user():用于将内核空间的数据复制到用户空间。通常在需要向用户程序返回数据时使用,比如内核完成某个操作后,将结果数据通过copy_to_user()复制到用户指定的缓冲区中,以便用户程序能够访问这些数据。
  • copy_from_user():作用是将用户空间的数据复制到内核空间。当用户程序向内核传递参数或数据时,内核需要使用copy_from_user()来获取用户空间的数据,例如用户程序通过系统调用向设备驱动传递配置信息等。

在 file_operations 结构中的应用

file_operations是 Linux 内核中用于描述文件操作的结构体,copy_to_user()和copy_from_user()一般用于以下函数:

  • read():从设备或文件读取数据到用户空间时,内核先从设备读取数据到内核空间缓冲区,再通过copy_to_user()将数据从内核空间缓冲区复制到用户提供的缓冲区。
  • write():用户程序向设备或文件写入数据时,copy_from_user()会将用户空间缓冲区中的数据复制到内核空间,然后内核再将数据写入设备或文件。
  • ioctl():在执行一些自定义的控制操作时,可能需要从用户空间获取参数或者向用户空间返回结果,此时也会用到copy_from_user()和copy_to_user()来进行数据的传递。

6 设备驱动程序中如何注册一个字符设备?分别解释一下它的几个参数的含义。⭐⭐⭐⭐

在 Linux 设备驱动里注册字符设备,可按以下步骤:

  • 分配设备号:用alloc_chrdev_region动态分配,或register_chrdev_region静态分配。alloc_chrdev_region(dev, baseminor, count, name)中,dev存储分配到的设备号;baseminor是起始次设备号;count是要分配的次设备号数量;name是设备名。
  • 初始化 cdev 结构体:用cdev_init关联设备操作函数。cdev_init(cdev, fops)里,cdev是struct cdev类型指针,代表字符设备;fops指向file_operations结构体,含设备操作函数。
  • 添加字符设备:使用cdev_add把cdev添加到内核。cdev_add(cdev, dev, count)中,cdev为要添加的字符设备;dev是设备号;count是设备数量。
  • 最后在驱动卸载时,用cdev_del移除cdev,unregister_chrdev_region释放设备号。

7 字符型驱动设备怎么创建设备文件?⭐⭐⭐

在 Linux 中,为字符型驱动设备创建设备文件通常有手动和自动两种方式:

手动创建设备文件

  • 使用mknod命令,其基本格式为mknod [设备文件名] c [主设备号] [次设备号]。例如,若主设备号为 200,次设备号为 0,要创建名为mychar的设备文件,可执行mknod /

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

嵌入式/C++面试八股文 文章被收录于专栏

#承诺提供免费技术答疑# 本专栏主要是介绍嵌入式开发岗位相关知识和学习攻略。“C/C++软件开发岗位”也可以参考。 该专栏覆盖了嵌入式求职过程中99%常见面试题,详细讲解了嵌入式软件开发岗位、学习攻略、项目经验分享、面试心得,从技术面,HR面,主管面,谈薪一站式服务。订阅即赠送简历模板、内推机会,需要的同学点击我头像私信即可!

全部评论

相关推荐

02-07 12:06
已编辑
华侨大学 测试开发
最近看到很多 92 的,甚至是硕士,开始往测开赛道卷,说实话有点看不懂。先把话说清楚,大厂里的测开,绝大多数时间干的还是测试的活,只是写点自动化脚本、维护测试平台、接接流水线,真正像开发一样做系统、做架构、做核心平台的测开少得可怜,基本都集中在核心提效组,而且人很少,外面进去的大概率轮不到你,我想真正干过人都清楚。很多人被洗脑了,以为测开也是开,和后端差不多,只是更简单、更轻松、还高薪。现实情况是,测开和开发的职业路径完全不一样。开发的核心是业务和系统能力,测开的核心是稳定性和覆盖率,前者是往上走,后者天花板非常明显。你可以见到很多开发转测开,但你很少见到干了几年测开还能顺利转回开发的。更现实一点说,92 的高学历如果拿来做测开,大部分时间就是在做重复性很强的杂活,这种工作对个人能力的放大效应非常弱。三年下来,你和一个双非的,甚至本科的测开差距不会太大,但你和同龄的后端、平台开发差距会非常明显。这不是努不努力的问题,是赛道问题。所谓测开简单高薪,本质上是把极少数核心测开的上限,当成了整个岗位的常态来宣传。那些工资高、技术强的测开,本身就是开发水平,只是挂了个测开的名。普通人进去,99% 做的都是项目兜底型工作,而不是你想象中的平台开发。测开不是不能做,但它绝对不是开发的平替,也不是性价比最优解。如果你是真的不想做开发,追求稳定,那测开没问题。但如果你只是觉得测开比后端容易,还能进大厂,那我劝你冷静一点,这只是在用短期安全感换长期天花板。有92的学历,如果你连测开这些重复性工作都能心甘情愿接受,那你把时间精力用在真正的开发、系统、业务深度上,回报大概率比卷测开要高得多。想清楚再下场,别被岗位名和话术带偏了,就算去个前端客户端也是随便占坑的,测开是一个坑位很少赛道,反而大面积学历下放,不用想也能知道会是什么结果,我想各位在JAVA那里已经看到了
小浪_Coding:工作只是谋生的手段 而不是相互比较和歧视
点赞 评论 收藏
分享
评论
点赞
3
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务