14.select和poll的区别?Poll和epoll的区别?
(1)select和poll的区别:(参考:http://blog.csdn.net/mituan2008/article/details/6695177)
二者根本的不同是:select()的fd_set是一个位掩码(bit mask),因此fd_set有固定的长度。内核在被编译的时候,可以不受这个长度的限制,因为select()允许应用程序自定义FD_SETSIZE的大小,但是这会增加额外的支出。
在调用poll()时需要自定义pollfd结构体数组并且需要指定数组的大小,所以呢这里原理上讲就是没有限制的。
(2)select和poll、epoll的区别(参考http://www.cnblogs.com/Anker/p/3265058.html)
A. select,poll实现需要自己不断轮询所有fd集合,直到设备就绪,期间可能要睡眠和唤醒多次交替。而epoll其实也需要调用epoll_wait不断轮询就绪链表,期间也可能多次睡眠和唤醒交替,但是它是设备就绪时,调用回调函数,把就绪fd放入就绪链表中,并唤醒在epoll_wait中进入睡眠的进程。虽然都要睡眠和交替,但是select和poll在“醒着”的时候要遍历整个fd集合,而epoll在“醒着”的时候只要判断一下就绪链表是否为空就行了,这节省了大量的CPU时间。这就是回调机制带来的性能提升。
B. select,poll每次调用都要把fd集合从用户态往内核态拷贝一次,并且要把current往设备等待队列中挂一次,而epoll只要一次拷贝,而且把current往等待队列上挂也只挂一次(在epoll_wait的开始,注意这里的等待队列并不是设备等待队列,只是一个epoll内部定义的等待队列)。这也能节省不少的开销。
C. select的几大缺点:
每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大;
同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大;
select支持的文件描述符数量太小了,默认是1024.
D. poll的实现和select非常相似,只是描述fd集合的方式不同,描述符数量不受限制,poll使用pollfd结构而不是select的fd_set结构,其他的都差不多。
15.谈谈对段页式管理的认识?什么时候会出现segment fault(段错误、缺页异常)?
什么是段页式管理?参考:http://blog.csdn.net/xiucaijiang/article/details/6818359
(http://zhan.renren.com/h5/entry/3602888497996214030
其实更好的讲解在ULK3 page376:缺页异常处理程序)
引入段页式管理的目的:为了获得分段在逻辑上的优点和分页在管理存储空间方面的优点。
(1)用分段方法来分配和管理虚拟存储器。把进程地址空间分成若干段,而每一段有自己的段名,把每一段分成若干页。
(2)用分页方法来分配和管理实存。即把整个主存分成大小相等的存储块,可装入作业的任何一页。
(3)逻辑地址结构的表示:一个逻辑地址用三个参数表示:段号S;页号P;页内地址d。
(4)段表、页表、段表地址寄存器。为了进行地址转换,系统为每个进程建立一个段表,并且要为该进程段表中的每一个段建立一个页表。系统中有一个段表地址寄存器来指出进程的段表起始地址和段表长度。
段页式管理的优缺点:
优点
(1)它提供了大量的虚拟存储空间。
(2)能有效地利用主存,为组织多道程序运行提供了方便。
缺点
(1)增加了硬件成本、系统的复杂性和管理上的开消。
(2)存在着系统发生抖动的危险。
(3)存在着内碎片。
(4)还有各种表格要占用主存空间。
段页式存储管理技术对当前的大、中型计算机系统来说,算是最通用、最灵活的一种方案。
什么时候会出现segment fault?内核中的机制是什么?
专业解释请参考ULK3 page376:缺页异常处理程序,哥现在还没怎么弄明白。
16.哈希表用来做什么?
哈希表也叫散列表,根据key value对数据进行分组,用于快速插入和查找
17.core文件的实现原理是什么?
请参考本博客:
http://blog.csdn.net/xuzhina/article/category/1322964
这哥儿们写了几十篇文章讲述core dump原理,我这里就不c-c,c-v了
如果面试官问道,就这么说吧(参考http://www.cnblogs.com/hazir/p/linxu_core_dump.html):
当程序运行的过程中异常终止或崩溃,操作系统会将程序当时的内存状态记录下来,保存在一个文件中,这种行为就叫做Core Dump(中文有的翻译成“核心转储”)。我们可以认为 core dump 是“内存快照”,但实际上,除了内存信息之外,还有些关键的程序运行状态也会同时 dump 下来,例如寄存器信息(包括程序指针、栈指针等)、内存管理信息、其他处理器和操作系统状态和信息。core dump 对于编程人员诊断和调试程序是非常有帮助的,因为对于有些程序错误是很难重现的,例如指针异常,而 core dump 文件可以再现程序出错时的情景。
18.fork返回0和大于0分别是进程?
返回值为0的是子进程,返回值大于0的是父进程,大于0的返回值为子进程的进程号,出错返回-1
函数说明:一个现有进程可以调用fork函数创建一个新进程。由fork创建的新进程被称为子进程(child process)。fork函数被调用一次但返回两次。两次返回的唯一区别是子进程中返回0值而父进程中返回子进程ID。子进程是父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。注意,子进程持有的是上述存储空间的“副本”,这意味着父子进程间不共享这些存储空间,它们之间共享的存储空间只有代码段。
19.程序执行时堆和栈用来做什么?
BSS段 data段 text段 堆heap 和 栈stack
BSS段:BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文Block Started by Symbol的简称。BSS段属于静态内存分配。
数据段:数据段(data segment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。
代码段:代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。
堆(heap):堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)
栈(stack):栈又称堆栈,是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。
20. 线程和进程的区别?
(http://www.cnblogs.com/flashsky/articles/642720.html)
线程是指进程内的一个执行单元,也是进程内的可调度实体.
与进程的区别:
(1)地址空间:线程共享进程的地址空间;而进程有自己独立的地址空间;
(2)资源拥有:线程共享进程的资源,进程是资源分配和拥有的单位
(3)线程是处理器调度的基本单位,但进程不是.
4)二者均可并发执行.
进一步展开:
进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。进程和线程的区别在于:
简而言之,一个程序至少有一个进程,一个进程至少有一个线程.
线程的划分尺度小于进程,使得多线程程序的并发性高。
另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.