微信公众号:javafirst
声明:问题是朋友提供的,回答是我自己写的,如不正确,和原作者无关。
一面(四十几分钟):
问题1 :自己设计实现一个信号量(口述思路)
利用FIFO(有名管道)实现。初始化创建一个管道并且往管道中写入value(value即为信号量的初始值)个字符。调用sem _post(解锁)往管道中写入一个字符,调用sem_wait(加锁)从管道中读取一个字符,如果管道为空则阻塞调用。还可以用共享内存实现,参考UNP卷二。
问题2 :Linux创建进程的几种方式,之间的区别
利用FIFO(有名管道)实现。初始化创建一个管道并且往管道中写入value(value即为信号量的初始值)个字符。调用sem _post(解锁)往管道中写入一个字符,调用sem_wait(加锁)从管道中读取一个字符,如果管道为空则阻塞调用。还可以用共享内存实现,参考UNP卷二。
问题2 :Linux创建进程的几种方式,之间的区别
fork:通过写时拷贝机制创建子进程,子进程通过拷贝父进程的页表与父进程共享相同的物理内存(被标记为只读),当其中一方试图修改物理内存上的数据时发生中断,内核拷贝被修改页并修改子进程的页表使其指向新拷贝的一页,之后对该页上的数据进行修改不再产生中断。因此可以理解成父进程和子进程拥有独立的地址空间而相互不干扰。
vfork:vfork之后,子进程先运行,当子进程调用exec或者exit后运行父进程。子进程和父进程共享地址空间,因此不论在父进程还是子进程中对数据的修改另一方是可见的。vfork设计是用来执行新程序的,即vfork后子进程马上调用exec系列函数。
问题3 :多态的实现机制
多态的定义即以一个父类的指针或引用,寻址出公有继承链中子类的实例。所以多态与继承有关,而实现多态需要借助虚函数。当以父类指针或引用调用虚函数时,实际运行的是父类指针或者引用所指向的实际对象中定义的虚函数。
虚函数的实现依靠的是一颗虚指针(和实例有关)和一张虚表(和类有关)。当一个虚函数被调用时,我并不知道具体是哪个类的虚函数,但我知道虚指针的偏移和虚函数所处虚表中的哪个槽,从而找到虚函数的入口地址并激活虚函数的调用。
问题4:malloc 和 new 的区别
malloc/free是C/C++标准库函数,new/delete是C++运算符。他们都可以用于动态申请和释放内存。
对于内置类型数据而言,二者没有多大区别。malloc申请内存的时候要制定分配内存的字节数,而且不会做初始化;new申请的时候有默认的初始化,同时可以指定初始化;
对于类类型的对象而言,用malloc/free无法满足要求的。对象在创建的时候要自动执行构造函数,消亡之前要调用析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制之内,不能把执行构造函数和析构函数的任务强加给它,因此,C++还需要new/delete。
问题5:不同类的占用内存大小
考虑内存对齐。
问题6:指针数组和数组指针的定义
指针数组:数组元素都是指针的数组。
数组指针:指向数组的指针。
问题7:升序链表的插入
问题8:一道算法题
问题9:Linux ( cd .. )基本操作指令
问题10:一个 shell程序
问题11:数据库 SQL 语句 - 多表查询( select grade, age from table1, table2 where table1.name=table2.name 等等)
问题12:如果让你去评测一款手机,你会怎么做
二面(十分钟):
问题1:普通进程与守护进程的区别
守护进程:脱离于终端并且在后台运行的进程。守护进程脱离于终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的信息所打断。服务器常被设计成守护进程。
普通进程:无法脱离终端,即便是后台进程,当终端被关掉时,进程也结束。
问题2:僵尸进程的概念
父进程未结束但是子进程已经结束并且父进程没有显式回收子进程资源。
问题3:了解过测试吗(并没有,但是测试很重要啊。。后面巴拉巴拉。。。)
三面(HR):
直接发的offer,除了问了下大概什么时间能到岗外,没有多说一句话,五分钟结束。。。
总结:总得来说,这次面试全程还算是轻松愉快的,问的都是基础知识
微信公众号:javafirst