腾讯后台开发类面试题(3)

  三. 守护进程实例

  守护进程实例包括两部分:主程序test.c和初始化程序init.c。主程序每隔一分钟向/tmp目录中的日志test.log报告运行状态。初始化程序中的init_daemon函数负责生成守护进程。读者可以利用init_daemon函数生成自己的守护进程。

  linux的内存管理机制是什么?

  Linux虚拟内存的实现需要6种机制的支持:地址映射机制、内存分配回收机制、缓存和刷新机制、请求页机制、交换机制和内存共享机制

  内存管理程序通过映射机制把用户程序的逻辑地址映射到物理地址。当用户程序运行时,如果发现程序中要用的虚地址没有对应的物理内存,就发出了请求页要求。如果有空闲的内存可供分配,就请求分配内存(于是用到了内存的分配和回收),并把正在使用的物理页记录在缓存中(使用了缓存机制)。如果没有足够的内存可供分配,那么就调用交换机制;腾出一部分内存。另外,在地址映射中要通过TLB(翻译后援存储器)来寻找物理页;交换机制中也要用到交换缓存,并且把物理页内容交换到交换文件中,也要修改页表来映射文件地址。

  linux的任务调度机制是什么?

  标准库函数和系统调用的区别?

  1、系统调用和库函数的关系

  系统调用通过软中断int 0x80从用户态进入内核态。

  函数库中的某些函数调用了系统调用。

  函数库中的函数可以没有调用系统调用,也可以调用多个系统调用。

  编程人员可以通过函数库调用系统调用。

  高级编程也可以直接采用int 0x80进入系统调用,而不必通过函数库作为中介。

  如果是在核心编程,也可以通过int 0x80进入系统调用,此时不能使用函数库。因为函数库中的函数是内核访问不到的。

  2、从用户调用库函数到系统调用执行的流程。

  1) 假设用户调用ssize_t write (int fields, cont void *buff, size_t nbytes);库函数。

  2) 库函数会执行int 0x80中断。因为中断使得进程从用户态进入内核态,所以参数通过寄存器传送。

  3) 0x80中断对应的中断例程被称为system call handler。其工作是:

  i. 存储大多数寄存器到内核堆栈中。这是汇编代码写的。

  ii. 执行真正的系统调用函数――system call service routine。这是C代码。

  iii. 通过ret_from_sys_call ()返回,回到用户态的库函数。这是汇编代码。

  1、系统调用

  系统调用提供的函数如open, close, read, write, ioctl等,需包含头文件unistd.h。以write为例:其函数原型为 size_t write(int fd, const void *buf, size_t nbytes),其操作对象为文件描述符或文件句柄fd(file descriptor),要想写一个文件,必须先以可写权限用open系统调用打开一个文件,获得所打开文件的fd,例如 fd=open(/"/dev/video/", O_RDWR)。fd是一个整型值,每新打开一个文件,所获得的fd为当前最大fd加1。Linux系统默认分配了3个文件描述符值:0-standard input,1-standard output,2-standard error。

  系统调用通常用于底层文件访问(low-level file access),例如在驱动程序中对设备文件的直接访问。

  系统调用是操作系统相关的,因此一般没有跨操作系统的可移植性。

  系统调用发生在内核空间,因此如果在用户空间的一般应用程序中使用系统调用来进行文件操作,会有用户空间到内核空间切换的开销。事实上,即使在用户空间使用库函数来对文件进行操作,因为文件总是存在于存储介质上,因此不管是读写操作,都是对硬件(存储器)的操作,都必然会引起系统调用。也就是说,库函数对文件的操作实际上是通过系统调用来实现的。例如C库函数fwrite()就是通过write()系统调用来实现的。

  这样的话,使用库函数也有系统调用的开销,为什么不直接使用系统调用呢?这是因为,读写文件通常是大量的数据(这种大量是相对于底层驱动的系统调用所实现的数据操作单位而言),这时,使用库函数就可以大大减少系统调用的次数。这一结果又缘于缓冲区技术。在用户空间和内核空间,对文件操作都使用了缓冲区,例如用fwrite写文件,都是先将内容写到用户空间缓冲区,当用户空间缓冲区满或者写操作结束时,才将用户缓冲区的内容写到内核缓冲区,同样的道理,当内核缓冲区满或写结束时才将内核缓冲区内容写到文件对应的硬件媒介。

  2、库函数调用

  标准C库函数提供的文件操作函数如fopen, fread, fwrite, fclose, fflush, fseek等,需包含头文件stdio.h。以fwrite为例,其函数原型为size_t fwrite(const void *buffer, size_t size, size_t item_num, FILE *pf),其操作对象为文件指针FILE *pf,要想写一个文件,必须先以可写权限用fopen函数打开一个文件,获得所打开文件的FILE结构指针pf,例如pf=fopen(/"~/proj/filename/", /"w/")。实际上,由于库函数对文件的操作最终是通过系统调用实现的,因此,每打开一个文件所获得的FILE结构指针都有一个内核空间的文件描述符fd与之对应。同样有相应的预定义的FILE指针:stdin-standard input,stdout-standard output,stderr-standard error。

  库函数调用通常用于应用程序中对一般文件的访问。

  库函数调用是系统无关的,因此可移植性好。

  由于库函数调用是基于C库的,因此也就不可能用于内核空间的驱动程序中对设备的操作

  ping命令所利用的原理是这样的:网络上的机器都有唯一确定的IP地址,我们给目标IP地址发送一个数据包,对方就要返回一个同样大小的数据包,根据返回的数据包我们可以确定目标主机的存在,可以初步判断目标主机的操作系统等。

  补充一个坑爹坑爹坑爹坑爹的问题:系统如何将一个信号通知到进程?(这一题哥没有答出来)

  c语言:

  宏定义和展开(必须精通)

  位操作(必须精通)

  指针操作和计算(必须精通)

  内存分配(必须精通)

  sizeof必考

  各类库函数必须非常熟练的实现

  哪些库函数属于高危函数,为什么?(strcpy等等)

  c++:

  一个String类的完整实现必须很快速写出来(注意:赋值构造,operator=是关键)

  虚函数的作用和实现原理(必问必考,实现原理必须很熟)

  有虚函数的类内部有一个称为“虚表”的指针(有多少个虚函数就有多少个指针),这个就是用来指向这个类虚函数。也就是用它来确定调用该那个函数。

  实际上在编译的时候,编译器会自动加入“虚表”。虚表的使用方法是这样的:如果派生类在自己的定义中没有修改基类的虚函数,就指向基类的虚函数;如果派生类改写了基类的虚函数(就是自己重新定义),这时虚表则将原来指向基类的虚函数的地址替换为指向自身虚函数的指针。那些被virtual关键字修饰的成员函数,就是虚函数。虚函数的作用,用专业术语来解释就是实现多态性(Polymorphism),多态性是将接口与实现进行分离;用形象的语言来解释就是实现以共同的方法,但因个体差异而采用不同的策略。

  每个类都有自己的vtbl,vtbl的作用就是保存自己类中虚函数的地址,我们可以把vtbl形象地看成一个数组,这个数组的每个元素存放的就是虚函数的地址,

  虚函数的效率低,其原因就是,在调用虚函数之前,还调用了获得虚函数地址的代码。

  sizeof一个类求大小(注意成员变量,函数,虚函数,继承等等对大小的影响)

更多面试问题推荐:

1.linux常见面试题及参考答案

2.常见主观面试题:如果你中500万会怎么花?

3.常见应届生面试题:你考虑过考研(考公务员)吗?

4.广告文案面试题

5.人力资源经理面试题集锦

6.应聘硬件工程师15道常见面试问题

7.英特尔Intel面试题

8.Java工程师三大框架面试题汇总

本文已影响6827
上一篇:2014最新行政助理面试问题 下一篇:迅雷历年常考面试题

相关文章推荐

|||||