嵌入式软件面试题(2)

1、请你说一说epoll的原理

调用顺序:
int epoll_create(int size);
int epoll_ctl(int epfd,int op,int fd,struct epoll_event *event);
int epoll_wait(int epfd,struct epoll_event *event,int maxevent,int timeout);
首先创建一个epoll对象,然后使用epoll_ctl对这个对象进行操作,把需要监控的描述符添加进去,这些描述符将会以epoll_event结构体的形式组成一颗红黑树,接着阻塞在epoll_wait,进入大循环,当某个fd上有事件发生时,内核将会把其对应的结构体放入到一个链表中,返回有事件发生的链表。

2、请你说说select,poll,epoll的区别,原理,性能,限制都说一说

答:select: 是最初解决IO阻塞问题的方法。用结构体fd_set来告诉内核监听多个文件描述符,该结构体被称为描述符集。由数组来维持哪些描述符被置位了。对结构体的操作封装在三个宏定义中。通过轮询的方式来查找是否有描述符要被处理。
存在的问题:1)内置数组的形式使得select的最大文件受限。
2)每次调用select前都要重新初始化描述符集,将fd中用户态拷贝到内核态,每 次调用select后,都需要将fd从内核态拷贝到用户态;
3)轮寻排查当文件描述符个数很多时,效率很低
poll:通过一个可变长度的数组解决了select文件描述符受限的问题。数组中的元素是结构体,该结构体保存描述符的信息,每增加一个文件描述符就向数组中加入一个结构体,结构体只需拷贝一次到内核态。poll解决了select重复初始化的问题,轮寻排查的问题未解决。
epoll:轮寻排查所有文件描述符的效率不高,使服务器并发能力受限。因此,epoll采用返回状态发生变化的文件描述符,便解决了轮寻的瓶颈。
epoll对文件描述符的操作有两种模式:LT和ET,LT是默认模式
LT模式:LT是缺省工作方式,并且同时支持block和no-block socket 。在这种做法中,内核告诉你一个文件描述符是否就绪,然后你可以对这个就绪的fd进行IO操作。如果你不做任何操作,内核还是会继续通知你。
ET模式:ET是高速工作方式,只支持no-block socket,在这种模式下,当描述符从未就绪变为就绪时,内核通过epoll告诉你。然后它会假设你知道文件描述符已经就绪,并且不会再为那个文件描述符发送更多的就绪通知,直到你做了某些操作导致那个文件描述符不再为就绪状态。
ET模式很大程度上减少了epoll事件被重复触发的次数,因此效率比LT模式高。epoll工作在ET模式的时候,必须使用非阻塞接口,以避免由于一个文件句柄阻塞读阻塞写操作把处理多个文件描述符的任务饿死。

3、map 和 set 有什么区别;

1) map 中的元素是 key—value (关键字–值)对,关键字起到索引的作用,值则表示与相关联的数据;set与之相对的就是关键字的简单集合,set每个元素只含一个关键字。
2)set 的迭代器是const的,不允许修改元素的值;map允许修改value,但不允许修改key。其原因是因为map和set是根据关键字排序来保证其有序性。如果允许修改key的话,那么首先需要删除该键,然后调节平衡,再插入修改后的键值,调节平衡,如此一来,严重破坏了map和set的结构,导致iterator失效,不知道应该指向改变前的位置,还是指向改变后的位置。所有STL中将 set 的迭代器设置成 const 不允许修改迭代器的值,而 map 的迭代器不允许修改 key 值, 允许修改 value 的值。
3)map 支持下标操作,set 不支持下标操作。map可以用 key 做下标,map 的下标运算符 [ ] 将关键字作为下标去执行查找,如果关键码不存在,则插入一个具有该关键码和 mapped_type 类型默认值的元素至map中,因此下标运算符 [ ] 在 map的应用中需慎用,const_map 不能用,只希望确定某一关键值是否存在而不希望插入元素时也不应该使用, mapped_type 类型没有默认值也不应该使用。如果find 能解决需要,尽可能用 find。

4、vector 和 list 的区别以及应用;

答:区别:
1)vector 底层实现的是数组;list 是双向链表
2)vector 支持随机访问,而 list 不支持
3) vector 是顺序访问, list 不是
4)vector 在中间节点进行插入和删除会导致内存拷贝,list 不会
5)vector 一次性分配好内存 ,不够时进行 2 倍扩容;list 每次插入新节点都会进行内存申请。
6)vector 随机访问性好,插入删除性能查差;list 随机访问性能差,插入删除性能好
应用:vector 拥有一段连续的内存空间,因此支持随机访问,如果需要高效的随机访问,而不在乎插入以及删除的效率的话,使用vector。
而list 拥有一段不连续的内存空间,如果需要高效的插入和删除,而不关心随机访问,则应用 list 。

5、请你说一说C++的内存管理是怎么样的;

答: 在C++中,虚拟内存分为代码段、数据段、BSS段、堆区、文件映射区以及栈区六部分。
代码段:包括只读存储区和文本区,其中只读存储区存储字符串常量,文本区存储程序的机器代码。
数据段:存储程序中的已初始化的全局变量和静态变量。
BSS段: 存储未初始化的全局变量和静态变量,以及所有被初始化为0的全局变量以及静态变量
堆区:调用 new/malloc函数时在堆区动态分配内存,同时需要调用delete/free来手动释放申请的内存。
映射区:存储动态链接库以及调用mmap函数将进行的文件映射
栈:使用栈空间存储函数的返回地址、参数、局部变量、返回值。

6、用变量a给出下面定义

1)一个指向整形数的指针 int *a;
2)一个指向指针的指针,它指向的指针是指向一个整形数 int **a;
3)一个有10个指针的数组,该指针指向一个整数型 int * a[10];
4)一个指向有十个整形数组的指针 int (*a)[10]
5)一个指向函数的指针,该函数有一个整型参数并返回一个整型数 int(*a)(int)
6)一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数 int (*a[10])(int)

7、如何引用一个已经定义过的全局变量

答:可以采用引用头文件的方式,也可以直接用 extern 关键字,如果引用 头文件的方式来引用某个在头文件声明的全局变量,假定你将那个变量写错了,那么在编译的时候会报错。而如果是用extern 的话,假如犯的是同样的错误,那么在编译期间是不会报错的,而是在连接的期间报错。

8、请你说一说操作系统中的缺页中断

答:malloc() 和mmap() 等内存分配函数,在分配时只是建立了进程虚拟地址空间,并没有分配虚拟内存对应的物理内存。当进程访问这些没有建立映射关系的虚拟内存时,处理器自动触发一个缺页异常。
缺页中断:在请求分页系统中,可以通过查询页表中的状态位来确定要访问的页面是否存在于内存中。每当所要访问的页面不在内存时,会产生一次缺页中断,此时操作系统会根据页表中的外存地址在外存中找到所缺的一页,将其调入内存。
缺页本身就是一种中断,与一般的中断一样,需要经过四个处理步骤:
1)保护CPU现场
2)分析中断原因
3)转入缺页中断处理程序进行处理
4)恢复CPU现场,继续执行
但是缺页中断是由于所要访问的页面不存在与内存时,由硬件所产生的一种特殊的中断,因此,与一般的中断存在区别:
1)在指令执行期间产生和处理缺页中断信号
2)一条指令在执行期间,可能产生多次缺页中断
3)缺页中断返回的是,执行产生中断的一条指令,而一般的中断返回的是,执行下一条指令。

9、请你说一说并发(concurrency)和并行(parallelism)

答:并发:是宏观上看起来两个程序在同时运行,比如说在单核CPU上的多任务。但是微观上看两个程序的指令是交织运行的,你的指令之间穿插着我的指令,我的指令之间穿插着你的指令。在单个周期内只运行了一个指令。这种并发并不能提高计算机的性能,只能提高效率。
并行:指严格物理意义上的同时运行,比如多核CPU,两个程序分别运行在两个核上,两者之间互不影响,单个周期内每一程序都运行了自己的指令,也就是运行了两条指令。这样来说并行的确提高了计算机的效率。所以CPU都是往多核方面发展的。

10、请你说一下多线程和多进程的不同

答:进程是资源分配的最小单位,而线程是CPU调度的最小单位。多线程之间共享同一个进程的地址空间,线程间通信简单,同步复杂,线程创建、销毁和切换简单,速度快,占用内存少,适用于多核分布式系统,但是线程间会相互影响,一个线程意外终止会导致一个进程的其他线程也终止,程序可靠性弱。而多进程拥有各自独立的运行地址空间,进程间不会相互影响,程序可靠性强,但是进程的创建、销毁和切换复杂,速度慢,占用内存多,进程间通信复杂,但是同步简单,使用于多核、多机分布。

11、请你说一说进程和线程的区别

答:线程是进程内的一个执行单元,也是进程内的可调度实体。
与进程的区别:
1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位
2)并发性:不仅进程间可以并发执行,同一个进程的多个线程间也可以并发执行。
3)拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但是可以访问隶属于进程的资源。
4)系统开销:在创建或撤销进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤销线程时的开销。
5)一个线程只能有一个进程,而一个进程可以有多个线程。

12、请你说一下进程与线程的概念。

答:进程是对运行程序的封装,是系统进行资源调度和分配的基本单位,实现了操作系统的并发;进程有五种状态(初始态、执行态、等待状态、就绪状态、终止状态)。
线程是进程的子任务,是CPU调度和分派的基本单位,用于保证程序的实时性,实现进程内部的并发;线程是操作系统可识别的最小执行和调度单位。线程的状态有就绪、执行、阻塞。

13、请问进程间怎样进行通信的

答:进程间的通信主要包括管道、消息队列、信号量、信号、共享内存、以及套接字socket
1)管道:管道主要包括有名管道和无名管道。
无名管道:a)它是半双工的,有固定的读端以及写端。
b)它只能用于有亲缘关系的进程之间的通信
c)它可以看成一种特殊的文件,对于它的读写可以使用普通的read、write等函数。但是它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中。
命名管道:a)命名管道(FIFO)可以在无关进程之间进行数据交换
b)命名管道有路径名与之相关联,它以一种特殊设备文件形式存在于文件系统中。
2)消息队列:是消息的链接表,存放于内核中。一个消息队列由一个标识符(既队列ID)来标记。(消息队列克服了信号传递信息少,管道只能承载无格式字节流以及缓冲区大小受限等特点)就有写权限地进程可以按照一定地规则向消息队列添加新消息。对消息队列有读权限的进程可以从消息队列中读取信息。
特点:
1)消息队列是面向记录的,其中的消息具有特特定的格式以及特定的优先级。
2)消息队列独立发送与接收进程。进程终止时,消息队列其内容并不会被删除。
3)消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按照消息的类型读取。
3)信号量:信号量与已经介绍过的IPC结构不同,它是一个计数器,可以用来控制多个进程对共享资源的访问,信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。
特点:1)信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。
2)信号量是基于操作系统PV操作。程序对信号量的操作都是原子操作。
3)每对信号量的PV操作不仅限于对信号量指加1或减1,而是可以加减任意正整数。
4)支持信号量组
4)信号:信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
5)共享内存:它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存数据的更新。这种方式需要依靠某种同步操作,如互斥锁和信号量等
特点:1)共享内存是最快的IPC,因为进程是直接对内存进行存取
2)因为多个进程可以同时操作,所以需要同步
3)信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问。
6)套接字socker:socket 是一种进程间通信机制,与其他通信机制不同的是,它可以用于不同主机之间的进程通信。

14、请问线程间怎样进行通信的

答:线程间的通信方式有临界区、互斥量、信号量、事件。
临界区:通过多线程的串化来访问公共资源或一段代码,速度快,适合控制数据访问。
互斥量:采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问。
信号量:为控制具有有限数量的用户资源而设计的,它允许多个线程在同一时刻去访问同一个资源,但一般需要限制同一个时刻访问此资源的最大线程数目。
事件:通过通知操作的方式来保持多线程同步,还可以方便实现多线程优先级的比较操作。

15、游戏服务器应该为每个用户开辟一个线程还是一个进程,为什么?

答:游戏服务器应该为每个用户开辟一个进程。因为同一线程间会相互影响,一个线程的死掉会影响其他线程,从而导致进程奔溃。因此为了保证不同的用户之间不会相互影响,应该为用户开辟一个进程。

16、请你说一下多进程和多线程的使用场景

答:多进程模型的优势是CPU。
多线程模型的主要优势是为线程间切换的代价较小,因此适用于I/O密集型的工作场景,因为I/O密集型的工作场景经常会由于I/O阻塞导致频繁的切换线程。同时,多线程模型也适用于单机多核分布式场景。
多进程模型,适用于CPU密集型。同时,多线程模型也适用于多机分布式场景中,易于多级扩展

17、Linux的用户模式和内核模式的区别

答:内核模式的代码可以无限地访问所有处理器指令集以及全部内存和I/O空间。如果用户模式的进程要享有这项特权,它必须通过系统调用向设备驱动程序或其他内核模式的代码发出请求。了。另外,用户模式的代码允许发生缺页,而内核模式的代码不允许。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值