[面试必备]嵌入式Linux内核开发必须了解的三十道题

简介: [面试必备]嵌入式Linux内核开发必须了解的三十道题

Linux的同步机制从2.0到2.6以来不断发展完善。从最初的原子操作,到后来的信号量,从大内核锁到今天的自旋锁。这些同步机制的发展伴随Linux从单处理器到对称多处理器的过渡。


伴随着从非抢占内核到抢占内核的过度。Linux的锁机制越来越有效,也越来越复杂。


1)Linux的内核锁主要是自旋锁和信号量。


自旋锁最多只能被一个可执行线程持有,如果一个执行线程试图请求一个已被争用(已经被持有)的自旋锁,那么这个线程就会一直进行忙循环——旋转——等待锁重新可用。要是锁未被争用,请求它的执行线程便能立刻得到它并且继续进行。自旋锁可以在任何时刻防止多于一个的执行线程同时进入临界区。


Linux中的信号量是一种睡眠锁。如果有一个任务试图获得一个已被持有的信号量时,信号量会将其推入等待队列,然后让其睡眠。这时处理器获得自由去执行其它代码。当持有信号量的进程将信号量释放后,在等待队列中的一个任务将被唤醒,从而便可以获得这个信号量。


信号量的睡眠特性,使得信号量适用于锁会被长时间持有的情况;只能在进程上下文中使用,因为中断上下文中是不能被调度的;另外当代码持有信号量时,不可以再持有自旋锁。


Linux 内核中的同步机制:原子操作、信号量、读写信号量和自旋锁的API,另外一些同步机制,包括大内核锁、读写锁、大读者锁、RCU (Read-Copy Update,顾名思义就是读-拷贝修改),和顺序锁。


2) Linux中的用户模式和内核模式是什么含意?


MS-DOS等操作系统在单一的CPU模式下运行,但是一些类Unix的操作系统则使用了双模式,可以有效地实现时间共享。在Linux机器上,CPU要么处于受信任的内核模式,要么处于受限制的用户模式。除了内核本身处于内核模式以外,所有的用户进程都运行在用户模式之中。


在2.4和更早的内核中,仅仅用户模式的进程可以被上下文切换出局,由其他进程抢占。除非发生以下两种情况,否则内核模式代码可以一直独占CPU:


  • (1) 它自愿放弃CPU;
  • (2) 发生中断或异常。


2.6内核引入了内核抢占,大多数内核模式的代码也可以被抢占。

【文章福利】小编推荐自己的Linux内核技术交流群: 865977150,整理了一些个人觉得比较好的学习书籍、视频资料共享在群文件里面,有需要的可以自行添加哦!!!前100名进群领取,额外赠送一份价值 699的内核资料包(含视频教程、电子书、实战项目及代码)


3) 怎样申请大块内核内存?


在Linux内核环境下,申请大块内存的成功率随着系统运行时间的增加而减少,虽然可以通过vmalloc系列调用申请物理不连续但虚拟地址连续的内存,但毕竟其使用效率不高且在32位系统上vmalloc的内存地址空间有限。所以,一般的建议是在系统启动阶段申请大块内存,但是其成功的概率也只是比较高而已,而不是100%。如果程序真的比较在意这个申请的成功与否,只能退用“启动内存”(Boot Memory)。


下面就是申请并导出启动内存的一段示例代码:

void* x_bootmem = NULL;
EXPORT_SYMBOL(x_bootmem);
unsigned long x_bootmem_size = 0;
EXPORT_SYMBOL(x_bootmem_size);
staTIc int __init x_bootmem_setup(char *str)
{
x_bootmem_size = memparse(str, &str);
x_bootmem = alloc_bootmem(x_bootmem_size);
printk(“Reserved %lu bytes from %p for x\n”, x_bootmem_size, x_bootmem);
return 1;
}
__setup(“x-bootmem=”, x_bootmem_setup);


可见其应用还是比较简单的,不过利弊总是共生的,它不可避免也有其自身的限制:


  • 内存申请代码只能连接进内核,不能在模块中使用。
  • 被申请的内存不会被页分配器和slab分配器所使用和统计,也就是说它处于系统的可见内存之外,即使在将来的某个地方你释放了它。
  • 一般用户只会申请一大块内存,如果需要在其上实现复杂的内存管理则需要自己实现。
  • 在不允许内存分配失败的场合,通过启动内存预留内存空间将是我们唯一的选择。


4) 用户进程间通信主要哪几种方式?


  • (1)管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行通信。
  • (2)命名管道(named pipe):命名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。命名管道在文件系统中有对应的文件名。命名管道通过命令mkfifo或系统调用mkfifo来创建。
  • (3)信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身;linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigacTIon(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigacTIon函数重新实现了signal函数)。
  • (4)消息(Message)队列:消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺
  • (5)共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
  • (6)信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。
  • (7)套接字(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和System V的变种都支持套接字。


5) 通过伙伴系统申请内核内存的函数有哪些?


在物理页面管理上实现了基于区的伙伴系统(zone based buddy system)。对不同区的内存使用单独的伙伴系统(buddy system)管理,而且独立地监控空闲页。相应接口alloc_pages(gfp_mask, order),_ _get_free_pages(gfp_mask, order)等。


6. Linux 虚拟文件系统的关键数据结构有哪些?(至少写出四个)


struct super_block,struct inode,struct file,struct dentry;


7. 对文件或设备的操作函数保存在那个数据结构中?


struct file_operations


8. Linux 中的文件包括哪些?


执行文件,普通文件,目录文件,链接文件和设备文件,管道文件。


9).创建进程的系统调用有那些?


clone(),fork(),vfork();系统调用服务例程:sys_clone,sys_fork,sys_vfork;


10. 调用 schedule()进行进程切换的方式有几种?


1.系统调用 do_fork();


2.定时中断 do_timer();


3.唤醒进程 wake_up_process


4.改变进程的调度策略 setscheduler();


5.系统调用礼让 sys_sched_yield();


11.Linux 调度程序是根据进程的动态优先级还是静态优先级来调度进程的?


Liunx 调度程序是根据根据进程的动态优先级来调度进程的,但是动态优先级又是根据静态优先级根据算法计算出来的,两者是两个相关联的值。因为高优先级的进程总是比低优先级的进程先被调度,为防止多个高优先级的进程占用 CPU 资源,导致其他进程不能占有 CPU,所以引用动态优先级概念


12.进程调度的核心数据结构是哪个?


struct runqueue


13.如何加载、卸载一个模块?


insmod 加载,rmmod 卸载


14. 模块和应用程序分别运行在什么空间?


模块运行在内核空间,应用程序运行在用户空间


15. Linux 中的浮点运算由应用程序实现还是内核实现?


应用程序实现,Linux 中的浮点运算是利用数学库函数实现的,库函数能够被应用程序链接后调用,不能被内核链接调用。这些运算是在应用程序中运行的,然后再把结果反馈给系统。Linux 内核如果一定要进行浮点运算,需要在建立内核时选上 math-emu,使用软件模拟计算浮点运算,据说这样做的代价有两个:用户在安装驱动时需要重建内核,可能会影响到其他的应用程序,使得这些应用程序在做浮点运算的时候也使用 math-emu,大大的降低了效率。


16. 模块程序能否使用可链接的库函数?


模块程序运行在内核空间,不能链接库函数。


17.TLB 中缓存的是什么内容?


TLB,页表缓存,当线性地址被第一次转换成物理地址的时候,将线性地址和物理地址的对应放到 TLB 中,用于下次访问这个线性地址时,加快转换速度。


18. Linux 中有哪几种设备?


字符设备和块设备。网卡是例外,他不直接与设备文件对应,mknod 系统调用用来创建设备文件。


19. 字符设备驱动程序的关键数据结构是哪个?


字符设备描述符 struct cdev,cdev_alloc()用于动态的分配 cdev 描述符,cdev_add()用于注册一个 cdev 描述符,cdev 包含一个 struct kobject 类型的数据结构它是核心的数据结构


20. 设备驱动程序包括哪些功能函数?


open(),read(),write(),llseek(),realse();


21. 如何唯一标识一个设备?


Linux 使用一个设备编号来唯一的标示一个设备,设备编号分为:主设备号和次设备号,一般主设备号标示设备对应的驱动程序,次设备号对应设备文件指向的设备,在内核中使用 dev_t 来表示设备编号,一般它是 32 位长度,其中 12 位用于表示主设备号,20 位用于表示次设备号,利用 MKDEV(int major,int minor);用于生成一个 dev_t 类型的对象。


22. Linux 通过什么方式实现系统调用?

软件中断实现的,首先,用户程序为系统调用设置参数,其中一个编号是系统调用编号,参数设置完成后,程序执行系统调用指令,x86 上的软中断是有 int 产生的,这个指令会导致一个异常,产生一个事件,这个事件会导致处理器跳转到内核态并跳转到一个新的地址。并开始处理那里的异常处理程序,此时的异常处理就是系统调用程序。


23. Linux 软中断和工作队列的作用是什么?

Linux 中的软中断和工作队列是中断处理。

1.软中断一般是“可延迟函数”的总称,它不能睡眠,不能阻塞,它处于中断上下文,不能进城切换,软中断不能被自己打断,只能被硬件中断打断(上半部),可以并发的运行在多个 CPU 上。所以软中断必须设计成可重入的函数,因此也需要自旋锁来保护其数据结构。

2.工作队列中的函数处在进程上下文中,它可以睡眠,也能被阻塞,能够在不同的进程间切换。已完成不同的工作。可延迟函数和工作队列都不能访问用户的进程空间,可延时函数在执行时不可能有任何正在运行的进程,工作队列的函数有内核进程执行,他不能访问用户空间地址。


24) TLB中缓存的是什么内容?


25) Linux中有哪几种设备?


26) 字符设备驱动程序的关键数据结构是哪个?


27) 设备驱动程序包括哪些功能函数?


28) 如何唯一标识一个设备?


29) Linux通过什么方式实现系统调用?


30) Linux软中断和工作队列的作用是什么?


相关文章
|
9天前
|
Linux 编译器 Android开发
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
在Linux环境下,本文指导如何交叉编译x265的so库以适应Android。首先,需安装cmake和下载android-ndk-r21e。接着,下载x265源码,修改crosscompile.cmake的编译器设置。配置x265源码,使用指定的NDK路径,并在配置界面修改相关选项。随后,修改编译规则,编译并安装x265,调整pc描述文件并更新PKG_CONFIG_PATH。最后,修改FFmpeg配置脚本启用x265支持,编译安装FFmpeg,将生成的so文件导入Android工程,调整gradle配置以确保顺利运行。
32 1
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
|
20天前
|
Linux C语言
Linux内核队列queue.h
Linux内核队列queue.h
|
27天前
|
JSON 机器人 Linux
推荐一款嵌入式Linux开源框架与封装-cpp-tbox
推荐一款嵌入式Linux开源框架与封装-cpp-tbox
54 3
|
10天前
|
Unix Linux Shell
FFmpeg开发笔记(八)Linux交叉编译Android的FFmpeg库
在Linux环境下交叉编译Android所需的FFmpeg so库,首先下载`android-ndk-r21e`,然后解压。接着,上传FFmpeg及相关库(如x264、freetype、lame)源码,修改相关sh文件,将`SYSTEM=windows-x86_64`改为`SYSTEM=linux-x86_64`并删除回车符。对x264的configure文件进行修改,然后编译x264。同样编译其他第三方库。设置环境变量`PKG_CONFIG_PATH`,最后在FFmpeg源码目录执行配置、编译和安装命令,生成的so文件复制到App工程指定目录。
43 9
FFmpeg开发笔记(八)Linux交叉编译Android的FFmpeg库
|
21天前
|
存储 Linux
linux查看系统版本、内核信息、操作系统类型版本
linux查看系统版本、内核信息、操作系统类型版本
56 9
|
1天前
|
弹性计算 网络协议 Shell
自动优化Linux 内核参数
【4月更文挑战第29天】
5 1
|
2天前
|
弹性计算 网络协议 Linux
自动优化 Linux 内核参数
【4月更文挑战第28天】
8 0
|
2天前
|
运维 监控 Unix
【专栏】Linux 系统管理员面试问题
【4月更文挑战第28天】本文概述了Linux系统管理员面试中的常见问题,涵盖基础知识、系统管理和故障排查。面试官会询问Linux与Unix的关系、内核功能、文件系统类型、权限位、用户组概念、链接类型、输入输出、进程和环境变量等。此外,还会涉及软件安装、服务配置、日志监控、网络管理、防火墙配置、LVM、RAID、用户管理、备份策略等实践技能。故障排查和脚本编程能力也是重点,包括系统故障分析、脚本在系统管理中的应用、磁盘空间管理、服务故障诊断及性能优化。准备面试的求职者应注重理论与实践经验的结合,持续学习以提升专业能力。
|
3天前
|
编解码 Linux
FFmpeg开发笔记(十二)Linux环境给FFmpeg集成libopus和libvpx
在《FFmpeg开发实战》一书中,介绍了如何在Linux环境下为FFmpeg集成libopus和libvpx,以支持WebM格式的Opus和VP8/VP9编码。首先,下载并安装libopus。接着,下载并安装libvpx。最后,在FFmpeg源码目录下,重新配置FFmpeg,启用libopus和libvpx,编译并安装。通过`ffmpeg -version`检查版本信息,确认libopus和libvpx已启用。
15 1
FFmpeg开发笔记(十二)Linux环境给FFmpeg集成libopus和libvpx
|
3天前
|
编解码 Linux
FFmpeg开发笔记(十)Linux环境给FFmpeg集成vorbis和amr
在Linux环境下,为FFmpeg添加对AAC、MP3、OGG和AMR音频格式的支持,需安装libogg、libvorbis和opencore-amr库。首先,从官方源下载各库的最新源码,如libogg-1.3.5、libvorbis-1.3.7和opencore-amr-0.1.6,然后解压并依次执行`./configure`、`make`和`make install`进行编译安装。接着,在FFmpeg源码目录中,使用`./configure`命令重新配置,并重新编译安装FFmpeg。最后,验证FFmpeg版本信息确认已启用ogg和amr支持。
15 0
FFmpeg开发笔记(十)Linux环境给FFmpeg集成vorbis和amr