嵌入式面试高频(实战场景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++,操作系统,ARM架构、RTOS、Linux基础、Linux驱动、Linux系统移植、计算机网络、数据结构与算法、数电基础、模电基础、5篇面试题目、HR面试常见问题汇总和嵌入式面试简历模板等文章。超全的嵌入式软件工程师面试题目和高频知识点总结! 另外,专栏分为两个部分,大家可以各取所好,为了有更好的阅读体验,后面会持续更新!!!