关于c++:30道最新Linux内核大厂面试题含答案

7次阅读

共计 6883 个字符,预计需要花费 18 分钟才能阅读完成。

  1. Linux 中次要有哪几种内核锁?

=====================

Linux 的同步机制从 2.0 到 2.6 以来一直倒退欠缺。从最后的原子操作,到起初 的信号量,从大内核锁到明天的自旋锁。这些同步机制的倒退随同 Linux 从单处 理器到对称多处理器的过渡;随同着从非抢占内核到抢占内核的适度。Linux 的 锁机制越来越无效,也越来越简单。自旋锁最多只能被一个可执行线程持有,如果一个执行线程试图申请一个已被争 用曾经被持有)的自旋锁,那么这个线程就会始终进行忙循环——旋转——期待 锁从新可用。要是锁未被争用,申请它的执行线程便能立即失去它并且持续进行。自旋锁能够在任何时刻避免多于一个的执行线程同时进入临界区。信号量的睡眠个性,使得信号量实用于锁会被长时间持有的状况;只能在过程上 下文中应用,因为中断上下文中是不能被调度的;另外当代码持有信号量时,不 能够再持有自旋锁。Linux 内核中的同步机制:原子操作、信号量、读写信号量和自旋锁的 API,另 外一些同步机制,包含大内核锁、读写锁、大读者锁、RCU (Read-Copy Update,顾名思义就是读 - 拷贝批改),和程序锁。

linux 内核视频解说:linux 内核文件系统具体实现与内核裁剪,含 30 道 linux 面试题

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

===========================

MS-DOS 等操作系统在繁多的 CPU 模式下运行,然而一些类 Unix 的操作系统则使 用了双模式,能够无效地实现工夫共享。在 Linux 机器上,CPU 要么处于受信赖 的内核模式,要么处于受限制的用户模式。除了内核自身处于内核模式以外,所 有的用户过程都运行在用户模式之中。内核模式的代码能够无限度地拜访所有处理器指令集以及全副内存和 I/O 空间。如果用户模式的过程要享有此特权,它必须通过零碎调用向设施驱动程序或其余 内核模式的代码发出请求。另外,用户模式的代码容许产生缺页,而内核模式的 代码则不容许。在 2.4 和更早的内核中,仅仅用户模式的过程能够被上下文切换出局,由其余进 程抢占。除非产生以下两种状况,否则内核模式代码能够始终独占 CPU:(1) 它被迫放弃 CPU;(2) 产生中断或异样。2.6 内核引入了内核抢占,大多数内核模式的代码也能够被抢占。

  1. 怎么申请大块内核内存?

===============

在 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 xn”, x_bootmem_size, x_bootmem); return 1; } __setup(“x-bootmem=”, x_bootmem_setup); 可见其利用还是比较简单的,不过利弊总是共生的,它不可避免也有其本身的限 制:内存申请代码只能连贯进内核,不能在模块中应用。被申请的内存不会被页调配 器和 slab 分配器所应用和统计,也就是说它处于零碎的可见内存之外,即便在 未来的某个中央你开释了它。个别用户只会申请一大块内存,如果须要在其上实 现简单的内存治理则须要本人实现。在不容许内存调配失败的场合,通过启动内 存预留内存空间将是咱们惟一的抉择。

  1. 用户过程间通信次要哪几种形式?

===================

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)信号量 semaphore):次要作为过程间以及同一过程不同线程之间的同步伎俩。

6)套接字 Socket):更为个别的过程间通信机制,可用于不同机器之间的过程间 通信。起初是由 Unix 零碎的 BSD 分支开发进去的,但当初个别能够移植到其它 类 Unix 零碎上:Linux 和 System V 的变种都反对套接字。

须要 C /C++ Linux 服务器架构师学习材料加群 563998835(材料包含 C /C++,Linux,golang 技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg 等),收费分享

  1. 通过搭档零碎申请内核内存的函数有哪些?

=======================

在物理页面治理上实现了基于区的搭档零碎 zone based buddy system)。对不 同区的内存应用独自的搭档零碎 (buddy system) 治理, 而且独立地监控闲暇页。相应接口 alloc_pages(gfp_mask, order),_ _get_free_pages(gfp_mask, order)等。

补充常识:

1. 原理阐明

  • 页全局目录(Page Global Directory)
  • 页两头目录(Page Middle Directory)

页全局目录蕴含若干页下级目录的地址,页下级目录又顺次蕴含若干页两头目录 的地址,而页两头目录又蕴含若干页表的地址,每一个页表项指 向一个页框。Linux 中采纳 4KB 大小的 页框作为规范的内存调配单元。

1.1. 搭档零碎算法 为了避免出现这种状况,Linux 内核中引入了搭档零碎算法(buddy system)。把 所有的闲暇页框分组为 11 个 块链表,每个块链表别离蕴含大小为 1,2,4,8,16,32,64,128,256,512 和 1024 个间断页框的页框块。最大能够申请 1024 个连 续页框,对应 4MB 大小的间断内存。每个页框块的第一个页框的物理地址 是该块大小的整数倍。页框块在开释时,会被动将两个间断的页框块合并为一个较大的页框块。slab 分配器源于 Solaris 2.4 的 调配算法,工作于物理内存页框分配器之上,治理特定大小对象的缓存,进行疾速而高效的内存调配。

2. 罕用内存调配函数 unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order) __get_free_pages 函数是最原始的内存调配形式,间接从搭档零碎中获取原始 页框,返回值为第一个页框的起始地址。__get_free_pages 在实现上只是封装 了 alloc_pages 函 数,从代码剖析,alloc_pages 函数会调配长度为 1< struct kmem_cache kmem_cache_create(const char name, size_t size void (ctor)(void, struct kmem_cache , unsigned long), void kmem_cache_alloc(struct kmem_cache c, gfp_t flags) kmem_cache_create/ kmem_cache_alloc 是基于 slab 分配器的一种内存调配方 式,实用于重复调配开释同一大小内存块的场合。首先用 kmem_cache_create 创 建一个高速缓存区域,而后用 kmem_cache_alloc 从 该高速缓存区域中获取新的 内存块。kmem_cache_alloc 一次能调配的最大内存由 mm/slab.c 文件中的 MAX_OBJ_ORDER 宏定义,在默认的 2.6.18 内核版本中,该宏定义为 5,于是一次最多能申请 1<<5 4KB 也就是 128KB 的间断物理内存。剖析内核源码发现,kmem_cache_create 函数的 size 参数大于 128KB 时会调用 BUG()。测试后果验证 了剖析后果,用 kmem_cache_create 调配超过 128KB 的内存时使内核解体。void *kmalloc(size_t size, gfp_t flags)

2.4.vmalloc 后面几种内存调配形式都是物理间断的,能保障较低的均匀拜访工夫。然而在某 些场合中,对内存区的申请不是很频繁,较高的内存拜访工夫也 能够承受,这 是就能够调配一段线性间断,物理不间断的地址,带来的益处是一次能够调配较 大块的内存。图 3-1 表 示的是 vmalloc 调配的内存应用的地址范畴。vmalloc 对 一次能调配的内存大小没有明确限度。出于性能思考,应审慎应用 vmalloc 函数。在测试过程中,最大能一次调配 1GB 的空间。

2.5.dma_alloc_coherent ma_addr_t *dma_handle, gfp_t gfp)

2.6.ioremap ioremap 是一种更间接的内存“调配”形式,应用时间接指定物理起始地址和需 要分配内存的大小,而后将该段 物理地址映射到内核地址空间。ioremap 用到 的物理地址空间都是当时确定的,和下面的几种内存 调配形式并不太一样,并 不是调配一段新的物理内存。ioremap 多用于设施驱动,能够让 CPU 间接拜访外 部设施的 IO 空间。ioremap 能映射的内存由原有的物理内存空间决定,所以没 有进行测试。如果要调配大量的间断物理内存,上述的调配函数都不能满足,就只能用比拟特 殊的形式,在 Linux 内 核疏导阶段来预留局部内存。void* alloc_bootmem(unsigned long size)

2.7.2. 通过内核疏导参数预留顶部内存 3. 几种调配函数的比拟 __get_free_pages 间接对页框进行操作 4MB 实用于调配较大量的间断物理内存 kmalloc 基于 kmem_cache_alloc 实现 128KB 最常见的调配形式,须要小于页框 大小的内存时能够应用 dma_alloc_coherent 基于__alloc_pages 实现 4MB 实用于 DMA 操 作 alloc_bootmem 在启动 kernel 时,预留一段内存,内核看不见小于物理内存大 小,内存治理要求较高

6、通过 slab 分配器申请内核内存的函数有?

7、Linux 的内核空间和用户空间是如何划分的(以 32 位零碎 为例)?

8、vmalloc()申请的内存有什么特点?

9、用户程序应用 malloc()申请到的内存空间在什么范畴?

10、在反对并使能 MMU 的零碎中,Linux 内核和用户程序分 别运行在物理地址模式还是虚拟地址模式?

11、ARM 处理器是通过几级也表进行存储空间映射的?

12、Linux 是通过什么组件来实现反对多种文件系通的?

虚构文件系统。

13、Linux 虚构文件系统的要害数据结构有哪些?(至多写出 四个)

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

14、对文件或设施的操作函数保留在那个数据结构中?

struct file_operations

15、Linux 中的文件包含哪些?

执行文件,一般文件,目录文件,链接文件和设施文件,管道文件。

16、创立过程的零碎调用有那些?

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

17、调用 schedule()进行过程切换的形式有几种?

1. 零碎调用 do_fork();

2. 定时中断 do_timer();

3. 唤醒过程 wake_up_process

4. 扭转过程的调度策略 setscheduler();

5. 零碎调用礼让 sys_sched_yield();

18、Linux 调度程序是依据过程的动静优先级还是动态优先级 来调度过程的?

Liunx 调度程序是依据依据过程的动静优先级来调度过程的,然而动静优先级又 是依据动态优先级依据算法计算出来的,两者是两个相关联的值。因为高优先级 的过程总是比低优先级的过程先被调度,为避免多个高优先级的过程占用 CPU 资 源,导致其余过程不能占有 CPU,所以援用动静优先级概念

19、过程调度的外围数据结构是哪个?

struct runqueue,struct task_struct, struct sched_struct

20、何加载、卸载一个模块?

insmod 加载,rmmod 卸载

21、模块和应用程序别离运行在什么空间?

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

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

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

23、模块程序是否应用可链接的库函数?

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

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

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

25、Linux 中有哪几种设施?

字符设施和块设施。网卡是例外,他不间接与设施文件对应,mknod 零碎调用用 来创立设施文件。

26、字符设施驱动程序的要害数据结构是哪个?

字符设施描述符 struct cdev,cdev_alloc()用于动静的调配 cdev 描述符,cdev_add()用于注册一个 cdev 描述符,cdev 蕴含一个 struct kobject 类型的 数据结构它是外围的数据结构

27、设施驱动程序包含哪些性能函数?

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

28、如何惟一标识一个设施?

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

29、Linux 通过什么形式实现零碎调用?

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

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

Linux 中的软中断和工作队列是中断解决。

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

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

正文完
 0