四个常见的Linux面试问题

Posted 分享IT资源

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了四个常见的Linux面试问题相关的知识,希望对你有一定的参考价值。

刚毕业要找工作了,只要是你找工作就会有面试这个环节,那么在面试环节中,有哪些注意事项值得我的关注呢?特别是专业技术岗位,这样的岗位询问一般都是在职的工程师,如何在面试环节更好地理解面试官的问题,我们一起往下看吧。

在学校学习也好,在培训机构或者网络在线学习也好,无论是通过那种途径,经过很长一段时间学习马上就要实践了,但是在面试的时候,还是没有把握,没关系来继续看吧~

  • Linux是什么?接触过那些Linux?

这一般是个入门的问题。此岗位对应聘者没有什么要求。只要你知道这个世界上有这么一个操作系统就行了。你完全可以按照所有书籍中的介绍,把Linux介绍给背出来,然后说说Red Hat\\ Ubuntu \\ Centos 等等,基本上这样你就能过关了。一般适合学历不高,应聘IDC运维这一类岗位。

  • 那些场景会用到Linux?

稍微进阶一点问题,主要看你是从事什么岗位,或者看你应聘的是什么岗位。我们以测试工程师为例,有如下场景会用使用的Linux:  1.如果当项目无法运行了,这个时候我们可以通过命令:ps -ef|grep XXX(进程名称)查看Linux服务上进程有没有正常启动。2.当运行的时候遇到BUG 的时候,我们可以通过命令:tail -100f xxx.log 查看最后100行日志内容,当然你也可以 -10 或者 -200,这个看个人习惯。

  • 你常用的Linux命令有哪些?

这个问题最重要的一点就是,不要死记硬背的说一堆Linux命令,背诵这些命令一点意义都没有。一定要去结合业务场景然后带出这个命令。就比如上面第二点距离说的测试工程师场景中。你就在脑海中想象一个场景,你经常用的命令,就可以像倒豆子一样,一串一串的倒出来了。(查看一个目录pwd-进入目录cd-创建文件夹mkdir-删除就用rm-复制移动就mv-查看文件内容cat more.。或者卡看网卡ifconfig – 进程无响应kill 一下)等等。这就像有画面一样,身临其境的操作。

  • 说说你对这个岗位的理解

当你遇到这个问题,一定要提前做好功课,知道自己面试的是什么岗位,我们不打没有准备的仗。我按照个人的理解把岗位分为三大类:运维、测试、开发。

1. 运维类:一般的IDC运维,这个你知道有Linux这个系统,背出常用命令基本可以过关;进阶服务器运维,这个一般都是有2-3年实际工作经验,能熟练操作主流Linxu系统Centos Redhat… 熟悉Shell脚本。面试这个岗位你需要熟练的列举你使用的工具和环境,可以说说ELK日志收集,监控警告系统Prometheus+Grafana。再说说日常给客户提供的服务FTP,常用环境 Java、 maven 、Nodejs ;还有中间件 eureka 、fastdfs、nacos 等。文件共享NFS,已经各种相关服务部署,docker 、web、最好能结合实际项目;而高级服务器运维这个属于行业类天花板了,都是行业大佬了,刚毕业的你,还是先从业10年再考虑吧。

2.测试类:测试相比较开发而言,主要的区别就是在写代码能力上。如果你有较强的编写代码能力,并且能在Linux上面非常深刻的理解,面试的时候一定要体现出来。先从基础开始,熟练描述软件测试流程,测试用例常用方法,BUG和缺陷的跟踪。然后说说各种测试工具:如抓包工具fiddier Charles 接口测试工具postman 性能测试工具jemeter loadrunner。进阶一点要谈谈自动化测试Python语言编写和jave语言编写。测试类很容易到天花板,如果你在行业中工作了3-8年还没有进入大国内大厂,那么天花板上的测试架构师,测试总监这样岗位也只能和你说拜拜了。

3. 开发类。 这个属于入门高天花板也高的一类,甚至你可以一直从普通的开发程序员一直走到开发总监,后期还可以跳到公司高管,或者转岗到其它赛道。当然这个进阶也有难度的,机遇和自己的努力是密不可分的。开发类面试主要是就项目了,说说你做过哪些项目,整个开发过程一说出来,你的水平自然就体现出来了。应用开发,嵌入式开发,服务器后台开发,底层开发,各个赛道如何选择根据你掌握的技能来定。

以上是《Linux就该这么学》整理的linux面试中常见的技巧和问题。综上所述,结合自己的实际能力,尽量的往更高一级别的方向去努力,当你接触的种类面越多,能力提升也就更快更全面,永远不要故步自封,力争在前中期进入大厂。各位学弟学妹们加油努力吧。

linux 后台开发类常见问题及知识点

一、linux和os:

  • netstat :显示网络状态

  • tcpdump:主要是截获通过本机网络接口的数据,用以分析。能够截获当前所有通过本机网卡的数据包。它拥有灵活的过滤机制,可以确保得到想要的数据。

  • ipcs:检查系统上共享内存的分配

  • ipcrm:手动解除系统上共享内存的分配

      (如果这四个命令没听说过或者不能熟练使用,基本上可以回家,通过的概率较小 ^_^ ,这四个命令的熟练掌握程度基本上能体现面试者实际开发和调试程序的经验)

      cpu 内存 硬盘 等等与系统性能调试相关的命令必须熟练掌握,设置修改权限 tcp网络状态查看 各进程状态 抓包相关等相关命令 必须熟练掌握

awk sed需掌握

1. 共享内存的使用实现原理

(必考必问,然后共享内存段被映射进进程空间之后,存在于进程空间的什么位置?共享内存段最大限制是多少?)

  共享内存定义:共享内存是最快的可用IPC(进程间通信)形式。它允许多个不相关的进程去访问同一部分逻辑内存。共享内存是由IPC为一个进程创建的一个特殊的地址范围,它将出现在进程的地址空间中。其他进程可以把同一段共享内存段“连接到”它们自己的地址空间里去。所有进程都可以访问共享内存中的地址。如果一个进程向这段共享内存写了数据,所做的改动会立刻被有访问同一段共享内存的其他进程看到。因此共享内存对于数据的传输是非常高效的。

  共享内存的原理:共享内存是最有用的进程间通信方式之一,也是最快的IPC形式。两个不同进程A、B共享内存的意思是,同一块物理内存被映射到进程A、B各自的进程地址空间。进程A可以即时看到进程B对共享内存中数据的更新,反之亦然。

2. c++进程内存空间分布(注意各部分的内存地址谁高谁低,注意栈从高到低分配,堆从低到高分配)

3. 使用过哪些进程间通讯机制,并详细说明(重点)

4. makefile编写,虽然比较基础,但是会被问到

5. gdb调试相关的经验,会被问到

6. 如何定位内存泄露?

  内存泄漏是指堆内存的泄漏。堆内存是指程序从堆中分配的、大小任意的(内存块的大小可以在程序运行期决定)、使用完后必须显示释放的内存。应用程序一般使用malloc、realloc、new等函数从堆中分配到一块内存,使用完后,程序必须负责相应的调用free或delete释放该内存块。否则,这块内存就不能被再次使用,我们就说这块内存泄漏了。

  C++程序缺乏相应的手段来检测内存信息,只能使用top指令观察进程的动态内存总额。而且程序退出时,我们无法获知任何内存泄漏信息

  使用Linux命令回收内存,可以使用ps、kill两个命令检测内存使用情况和进行回收。在使用超级用户权限时使用命令“ps”,它会列出所有正在运行的程序名称和对应的进程号(PID)。kill命令的工作原理是向Linux操作系统的内核送出一个系统操作信号和程序的进程号(PID)

7. 动态链接和静态链接的区别

动态链接是指在生成可执行文件时不将所有程序用到的函数链接到一个文件,因为有许多函数在操作系统带的dll文件中,当程序运行时直接从操作系统中找。 而静态链接就是把所有用到的函数全部链接到exe文件中。

  动态链接是只建立一个引用的接口,而真正的代码和数据存放在另外的可执行模块中,在运行时再装入;而静态链接是把所有的代码和数据都复制到本模块中,运行时就不再需要库了。

8. 32位系统一个进程最多有多少堆内存

9. 多线程和多进程的区别

重点 面试官最最关心的一个问题,必须从cpu调度,上下文切换,数据共享,多核cup利用率,资源占用,等等各方面回答,然后有一个问题必须会被问到:哪些东西是一个线程私有的?答案中必须包含寄存器,否则悲催

10. 说出你所知道的linux系统的各类同步机制(重点)

11. 什么是死锁?如何避免死锁(每个技术面试官必问)

12. 死锁的条件

(互斥条件(Mutual exclusion):

  1、资源不能被共享,只能由一个进程使用。

  2、请求与保持条件(Hold and wait):已经得到资源的进程可以再次申请新的资源。

  3、非剥夺条件(No pre-emption):已经分配的资源不能从相应的进程中被强制地剥夺。

  4、循环等待条件(Circular wait):系统中若干进程组成环路,该环路中每个进程都在等待相邻进程正占用的资源。

13. 处理死锁的策略:

  1. 忽略该问题。例如鸵鸟算法,该算法可以应用在极少发生死锁的的情况下。为什么叫鸵鸟算法呢,因为传说中鸵鸟看到危险就把头埋在地底下,可能鸵鸟觉得看不到危险也就没危险了吧。跟掩耳盗铃有点像。
  2. 检测死锁并且恢复。
  3. 仔细地对资源进行动态分配,以避免死锁。
  4. 通过破除死锁四个必要条件之一,来防止死锁产生。)

14. 列举说明linux系统的各类异步机制

15. exit()与_exit()的区别?

  _exit终止调用进程,但不关闭文件,不清除输出缓存,也不调用出口函数。exit函数将终止调用进程。在退出程序之前,所有文件关闭,缓冲输出内容将刷新定义,并调用所有已刷新的“出口函数”(由atexit定义)。

  ‘exit()’与‘_exit()’有不少区别在使用‘fork()’,特别是‘vfork()’时变得很突出。

  ‘exit()’与‘_exit()’的基本区别在于前一个调用实施与调用库里用户状态结构(user-mode constructs)有关的清除工作(clean-up),而且调用用户自定义的清除程序

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

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

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

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

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

19. 系统如何将一个信号通知到进程

二、c语言:

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

  • 位操作(必须精通)

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

  • 内存分配(必须精通)

  • sizeof必考

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

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

三、c++:

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

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

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

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

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

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

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

4. 指针和引用的区别(一般都会问到)

指针指向一块内存,它的内容是所指内存的地址;而引用是某块内存的别名。

相同点: 都是地址的概念;

区别:

  1. 指针是一个实体,而引用仅是个别名;
  2. 引用使用时无需解引用(*),指针需要解引用;
  3. 引用只能在定义时被初始化一次,之后不可变;指针可变;
  4. 引用没有 const,指针有 const;
  5. 引用不能为空,指针可以为空;
  6. “sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身(所指向的变量或对象的地址)的大小;
  7. 指针和引用的自增(++)运算意义不一样;
  8. 从内存分配上看:程序为指针变量分配内存区域,而引用不需要分配内存区域。

5. 多重类构造和析构的顺序

先调用基类的构造函数,在调用派生类的构造函数

先构造的后析构,后构造的先析构

6. stl各容器的实现原理(必考)

  STL共有六大组件

  1、容器。2、算法。3、迭代器。4、仿函数。6、适配器。

  序列式容器:

  vector-数组,元素不够时再重新分配内存,拷贝原来数组的元素到新分配的数组中。

  list-单链表。

  deque-分配中央控制器map(并非map容器),map记录着一系列的固定长度的数组的地址.记住这个map仅仅保存的是数组的地址,真正的数据在数组中存放着.deque先从map中央的位置(因为双向队列,前后都可以插入元素)找到一个数组地址,向该数组中放入数据,数组不够时继续在map中找空闲的数组来存数据。当map也不够时重新分配内存当作新的map,把原来map中的内容copy的新map中。所以使用deque的复杂度要大于vector,尽量使用vector。

  stack-基于deque。

  queue-基于deque。

  heap-完全二叉树,使用最大堆排序,以数组(vector)的形式存放。

  priority_queue-基于heap。

  slist-双向链表。

  关联式容器:

  set,map,multiset,multimap-基于红黑树(RB-tree),一种加上了额外平衡条件的二叉搜索树。

  hash table-散列表。将待存数据的key经过映射函数变成一个数组(一般是vector)的索引,例如:数据的key%数组的大小=数组的索引(一般文本通过算法也可以转换为数字),然后将数据当作此索引的数组元素。有些数据的key经过算法的转换可能是同一个数组的索引值(碰撞问题,可以用线性探测,二次探测来解决),STL是用开链的方法来解决的,每一个数组的元素维护一个list,他把相同索引值的数据存入一个list,这样当list比较短时执行删除,插入,搜索等算法比较快。

  hash_map,hash_set,hash_multiset,hash_multimap-基于hash table。

7. extern c 是干啥的,(必须将编译器的函数名修饰的机制解答的很透彻)

8. volatile是干啥用的,(必须将cpu的寄存器缓存机制回答的很透彻)

  volatile的本意是“易变的” 因为访问寄存器要比访问内存单元快的多,所以编译器一般都会作减少存取内存的优化,但有可能会读脏数据。当要求使用volatile声明变量值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。精确地说就是,遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问;如果不使用volatile,则编译器将对所声明的语句进行优化。(简洁的说就是:volatile关键词影响编译器编译的结果,用volatile声明的变量表示该变量随时可能发生变化,与该变量有关的运算,不要进行编译优化,以免出错)

volatile的本质:

  1. 编译器的优化

      在本次线程内, 当读取一个变量时,为提高存取速度,编译器优化时有时会先把变量读取到一个寄存器中;以后,再取变量值时,就直接从寄存器中取值;当变量值在本线程里改变时,会同时把变量的新值copy到该寄存器中,以便保持一致。

      当变量在因别的线程等而改变了值,该寄存器的值不会相应改变,从而造成应用程序读取的值和实际的变量值不一致。

      当该寄存器在因别的线程等而改变了值,原变量的值不会改变,从而造成应用程序读取的值和实际的变量值不一致。

  2. volatile应该解释为“直接存取原始内存地址”比较合适,“易变的”这种解释简直有点误导人。

9. static const等等的用法,(能说出越多越好)

四、数据结构或者算法:

  • 各类树结构的实现和应用

  • 各类排序:大根堆的实现,快排(如何避免最糟糕的状态?),bitmap的运用等等

  • hash, 任何一个技术面试官必问(例如为什么一般hashtable的桶数会取一个素数?如何有效避免hash结果值的碰撞)

五、网络编程:

1. tcp与udp的区别(必问)

  1. 基于连接与无连接
  2. 对系统资源的要求(TCP较多,UDP少)
  3. UDP程序结构较简单
  4. 流模式与数据报模式
  5. TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证

      TCP—传输控制协议,提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。

      UDP—用户数据报协议,是一个简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快

2. socket服务端的实现,select和epoll的区别(必问)

  select的本质是采用32个整数的32位,即32*32= 1024来标识,fd值为1-1024。当fd的值超过1024限制时,就必须修改FD_SETSIZE的大小。这个时候就可以标识32*max值范围的fd。

  对于单进程多线程,每个线程处理多个fd的情况,select是不适合的。

  1.所有的线程均是从1-32*max进行扫描,每个线程处理的均是一段fd值,这样做有点浪费

  2.1024上限问题,一个处理多个用户的进程,fd值远远大于1024

  所以这个时候应该采用poll,

  poll传递的是数组头指针和该数组的长度,只要数组的长度不是很长,性能还是很不错的,因为poll一次在内核中申请4K(一个页的大小来存放fd),尽量控制在4K以内

  epoll还是poll的一种优化,返回后不需要对所有的fd进行遍历,在内核中维持了fd的列表。select和poll是将这个内核列表维持在用户态,然后传递到内核中。但是只有在2.6的内核才支持。

  epoll更适合于处理大量的fd ,且活跃fd不是很多的情况,毕竟fd较多还是一个串行的操作

  epoll哪些触发模式,有啥区别?(必须非常详尽的解释水平触发和边缘触发的区别,以及边缘触发在编程中要做哪些更多的确认)

  epoll可以同时支持水平触发和边缘触发(Edge Triggered,只告诉进程哪些文件描述符刚刚变为就绪状态,它只说一遍,如果我们没有采取行动,那么它将不会再次告知,这种方式称为边缘触发),理论上边缘触发的性能要更高一些,但是代码实现相当复杂。

  epoll同样只告知那些就绪的文件描述符,而且当我们调用epoll_wait()获得就绪文件描述符时,返回的不是实际的描述符,而是一个代表就绪描述符数量的值,你只需要去epoll指定的一个数组中依次取得相应数量的文件描述符即可,这里也使用了内存映射(mmap)技术,这样便彻底省掉了这些文件描述符在系统调用时复制的开销。

  另一个本质的改进在于epoll采用基于事件的就绪通知方式。在select/poll中,进程只有在调用一定的方法后,内核才对所有监视的文件描述符进行扫描,而epoll事先通过epoll_ctl()来注册一个文件描述符,一旦基于某个文件描述符就绪时,内核会采用类似callback的回调机制,迅速激活这个文件描述符,当进程调用epoll_wait()时便得到通知。

3. 大规模连接上来,并发模型怎么设计

4. tcp结束连接怎么握手,time_wait状态是什么,为什么会有time_wait状态?哪一方会有time_wait状态,如何避免time_wait状态占用资源(必须回答的详细)

5. tcp头多少字节?哪些字段?(必问)

头20字节,选项12字节

6. connect会阻塞,怎么解决?(必考必问)

最通常的方法最有效的是加定时器;也可以采用非阻塞模式。

设置非阻塞,返回之后用select检测状态)

如果select返回可读,结果只读到0字节,什么情况?

某个套接字集合中没有准备好,可能会select内存用FD_CLR清该位为0;

参考:http://mianshi.cnrencai.com/mianshiwenti/3229_4.html

以上是关于四个常见的Linux面试问题的主要内容,如果未能解决你的问题,请参考以下文章

Linux运维常见基础面试练习题

Linux运维常见基础面试练习题

Linux运维常见基础面试练习题

linux系统运维企业常见面试题集合

Linux运维常见基础面试练习题

Linux运维常见基础面试练习题