linux后台开发面试题

网络

  1. 网络的字节序
  2. 网络知识 tcp三次握手 各种细节 timewait状态
  3. tcp 与 udp 区别 概念 适用范围
  4. TCP四次挥手讲一下过程,最后一次ack如果客户端没收到怎么办,为什么挥手不能只有三次,为什么time_wait。
  5. 对于socket编程,accept方法是干什么的,在三次握手中属于第几次,可以猜一下,为什么这么觉得。
  6. tcp怎么保证有序传输的,讲下tcp的快速重传和拥塞机制,知不知道time_wait状态,这个状态出现在什么地方,有什么用?
  7. 知道udp是不可靠的传输,如果你来设计一个基于udp差不多可靠的算法,怎么设计?
  8. http与https有啥区别?说下https解决了什么问题,怎么解决的?说下https的握手过程。
  9. tcp 粘包半包问题怎么处理?
  10. keepalive 是什么东东?如何使用?
  11. 列举你所知道的tcp选项,并说明其作用。
  12. socket什么情况下可读?
  13. nginx的epoll模型的介绍以及io多路复用模型
  14. SYN Flood攻击
  15. 流量控制,拥塞控制
  16. TCP和UDP区别,TCP如何保证可靠性,对方是否存活(心跳检测)
  17. tcpdump抓包,如何分析数据包
  18. tcp如何设定超时时间
  19. 基于socket网络编程和tcp/ip协议栈,讲讲从客户端send()开始,到服务端recv()结束的过程,越细越好
  20. http报文格式
  21. http1.1与http1.0区别,http2.0特性
  22. http3了解吗
  23. http1.1长连接时,发送一个请求阻塞了,返回什么状态码?
  24. udp调用connect有什么作用?
  25. TCP与UDP之间的区别
    (1) IP首部,TCP首部,UDP首部
    (2) TCP和UDP区别
    (3) TCP和UDP应用场景
    (4) 如何实现可靠的UDP
  26. TCP三次握手与四次挥手
  27. 详细说明TCP状态迁移过程
    (1) 三次握手和四次挥手状态变化;
    (2) 2MSL是什么状态?作用是什么?
    (3)三次握手为什么不是两次或者四次?
  28. TCP相关技术
  29. TCP重发机制,Nagle算法
  30. TCP的拥塞控制使用的算法和具体过程
  31. TCP的窗口滑动
  32. TCP客户与服务器模型,用到哪些函数
  33. UDP客户与服务器模型,用到哪些函数
  34. 域名解析过程,ARP的机制,RARP的实现
  35. Ping和TraceRoute实现原理
  36. 如果请求出现问题没有响应,如何定位问题,说下思路?

操作系统

  1. 进程和线程-分别的概念 区别 适用范围 它们分别的通讯方式 不同通讯方式的区别优缺点
  2. 僵尸进程
  3. 死锁是怎么产生的
  4. CPU的执行方式
  5. 代码中遇到进程阻塞,进程僵死,内存泄漏等情况怎么排查。
  6. 有没有了解过协程?说下协程和线程的区别?
  7. 堆是线程共有还是私有,堆是进程共有还是私有,栈呢
  8. 了解过协程吗(我:携程???不了解呜呜呜)
  9. 共享内存的使用实现原理(必考必问,然后共享内存段被映射进进程空间之后,存在于进程空间的什么位置?共享内存段最大限制是多少?)
  10. c++进程内存空间分布(注意各部分的内存地址谁高谁低,注意栈从高道低分配,堆从低到高分配)
  11. ELF是什么?其大小与程序中全局变量的是否初始化有什么关系(注意.bss段)
  12. 使用过哪些进程间通讯机制,并详细说明(重点)
  13. 多线程和多进程的区别(重点 面试官最最关心的一个问题,必须从cpu调度,上下文切换,数据共享,多核cup利用率,资源占用,等等各方面回答,然后有一个问题必须会被问到:哪些东西是一个线程私有的?答案中必须包含寄存器,否则悲催)
  14. 信号:列出常见的信号,信号怎么处理?
  15. i++是否原子操作?并解释为什么???????
  16. 说出你所知道的各类linux系统的各类同步机制(重点),什么是死锁?如何避免死锁(每个技术面试官必问)
  17. 列举说明linux系统的各类异步机制
  18. exit() _exit()的区别?
  19. 如何实现守护进程?
  20. linux的内存管理机制是什么?
  21. linux的任务调度机制是什么?
  22. 标准库函数和系统调用的区别?
  23. 补充一个坑爹坑爹坑爹坑爹的问题:系统如何将一个信号通知到进程?(这一题哥没有答出来)
  • fork与vfork区别
    fork和vfork都用于创建子进程。但是vfork创建子进程后,父进程阻塞,直到子进程调用exit()或者excle()。
    对于内核中过程fork通过调用clone函数,然后clone函数调用do_fork()。do_fork()中调用copy_process()函数先复制task_struct结构体,然后复制其他关于内存,文件,寄存器等信息。fork采用写时拷贝技术,因此子进程和父进程的页表指向相同的页框。但是vfork不需要拷贝页表,因为父进程会一直阻塞,直接使用父进程页表。
  • exit()与_exit()区别
    exit()清理后进入内核,_exit()直接陷入内核。
  • 孤儿进程与僵死进程
  1. 孤儿进程是怎么产生的?
  2. 僵死进程是怎么产生的?
  3. 僵死进程的危害?
  4. 如何避免僵死进程的产生?
  1. 伙伴算法,用于管理物理内存,避免内存碎片;
  2. 高速缓存Slab层用于管理内核分配内存,避免碎片。
  1. 互斥锁,自旋锁,信号量,读写锁,屏障
  2. 互斥锁与自旋锁的区别:互斥锁得不到资源的时候阻塞,不占用cpu资源。自旋锁得不到资源的时候,不停的查询,而然占用cpu资源。
  3. 死锁​​​​​​
  4. 命令:netstat tcpdump ipcs ipcrm

    这四个命令的熟练掌握程度基本上能体现实际开发和调试程序的经验

Effective C++

  1. 视 C++ 为一个语言联邦(C、Object-Oriented C++、Template C++、STL)
  2. 宁可以编译器替换预处理器(尽量以 constenuminline 替换 #define
  3. 尽可能使用 const
  4. 确定对象被使用前已先被初始化(构造时赋值(copy 构造函数)比 default 构造后赋值(copy assignment)效率高)
  5. 了解 C++ 默默编写并调用哪些函数(编译器暗自为 class 创建 default 构造函数、copy 构造函数、copy assignment 操作符、析构函数)
  6. 若不想使用编译器自动生成的函数,就应该明确拒绝(将不想使用的成员函数声明为 private,并且不予实现)
  7. 为多态基类声明 virtual 析构函数(如果 class 带有任何 virtual 函数,它就应该拥有一个 virtual 析构函数)
  8. 别让异常逃离析构函数(析构函数应该吞下不传播异常,或者结束程序,而不是吐出异常;如果要处理异常应该在非析构的普通函数处理)
  9. 绝不在构造和析构过程中调用 virtual 函数(因为这类调用从不下降至 derived class)
  10. 令 operator= 返回一个 reference to *this (用于连锁赋值)
  11. 在 operator= 中处理 “自我赋值”
  12. 赋值对象时应确保复制 “对象内的所有成员变量” 及 “所有 base class 成分”(调用基类复制构造函数)
  13. 以对象管理资源(资源在构造函数获得,在析构函数释放,建议使用智能指针,资源取得时机便是初始化时机(Resource Acquisition Is Initialization,RAII))
  14. 在资源管理类中小心 copying 行为(普遍的 RAII class copying 行为是:抑制 copying、引用计数、深度拷贝、转移底部资源拥有权(类似 auto_ptr))
  15. 在资源管理类中提供对原始资源(raw resources)的访问(对原始资源的访问可能经过显式转换或隐式转换,一般而言显示转换比较安全,隐式转换对客户比较方便)
  16. 成对使用 new 和 delete 时要采取相同形式(new 中使用 [] 则 delete []new 中不使用 [] 则 delete
  17. 以独立语句将 newed 对象存储于(置入)智能指针(如果不这样做,可能会因为编译器优化,导致难以察觉的资源泄漏)
  18. 让接口容易被正确使用,不易被误用(促进正常使用的办法:接口的一致性、内置类型的行为兼容;阻止误用的办法:建立新类型,限制类型上的操作,约束对象值、消除客户的资源管理责任)
  19. 设计 class 犹如设计 type,需要考虑对象创建、销毁、初始化、赋值、值传递、合法值、继承关系、转换、一般化等等。
  20. 宁以 pass-by-reference-to-const 替换 pass-by-value (前者通常更高效、避免切割问题(slicing problem),但不适用于内置类型、STL迭代器、函数对象)
  21. 必须返回对象时,别妄想返回其 reference(绝不返回 pointer 或 reference 指向一个 local stack 对象,或返回 reference 指向一个 heap-allocated 对象,或返回 pointer 或 reference 指向一个 local static 对象而有可能同时需要多个这样的对象。)
  22. 将成员变量声明为 private(为了封装、一致性、对其读写精确控制等)
  23. 宁以 non-member、non-friend 替换 member 函数(可增加封装性、包裹弹性(packaging flexibility)、机能扩充性)
  24. 若所有参数(包括被this指针所指的那个隐喻参数)皆须要类型转换,请为此采用 non-member 函数
  25. 考虑写一个不抛异常的 swap 函数
  26. 尽可能延后变量定义式的出现时间(可增加程序清晰度并改善程序效率)
  27. 尽量少做转型动作(旧式:(T)expressionT(expression);新式:const_cast<T>(expression)dynamic_cast<T>(expression)reinterpret_cast<T>(expression)static_cast<T>(expression)、;尽量避免转型、注重效率避免 dynamic_casts、尽量设计成无需转型、可把转型封装成函数、宁可用新式转型)
  28. 避免使用 handles(包括 引用、指针、迭代器)指向对象内部(以增加封装性、使 const 成员函数的行为更像 const、降低 “虚吊号码牌”(dangling handles,如悬空指针等)的可能性)
  29. 为 “异常安全” 而努力是值得的(异常安全函数(Exception-safe functions)即使发生异常也不会泄露资源或允许任何数据结构败坏,分为三种可能的保证:基本型、强列型、不抛异常型)
  30. 透彻了解 inlining 的里里外外(inlining 在大多数 C++ 程序中是编译期的行为;inline 函数是否真正 inline,取决于编译器;大部分编译器拒绝太过复杂(如带有循环或递归)的函数 inlining,而所有对 virtual 函数的调用(除非是最平淡无奇的)也都会使 inlining 落空;inline 造成的代码膨胀可能带来效率损失;inline 函数无法随着程序库的升级而升级)
  31. 将文件间的编译依存关系降至最低(如果使用 object references 或 object pointers 可以完成任务,就不要使用 objects;如果能够,尽量以 class 声明式替换 class 定义式;为声明式和定义式提供不同的头文件)
  32. 确定你的 public 继承塑模出 is-a(是一种)关系(适用于 base classes 身上的每一件事情一定适用于 derived classes 身上,因为每一个 derived class 对象也都是一个 base class 对象)
  33. 避免遮掩继承而来的名字(可使用 using 声明式或转交函数(forwarding functions)来让被遮掩的名字再见天日)
  34. 区分接口继承和实现继承(在 public 继承之下,derived classes 总是继承 base class 的接口;pure virtual 函数只具体指定接口继承;非纯 impure virtual 函数具体指定接口继承及缺省实现继承;non-virtual 函数具体指定接口继承以及强制性实现继承)
  35. 考虑 virtual 函数以外的其他选择(如 Template Method 设计模式的 non-virtual interface(NVI)手法,将 virtual 函数替换为 “函数指针成员变量”,以 tr1::function 成员变量替换 virtual 函数,将继承体系内的 virtual 函数替换为另一个继承体系内的 virtual 函数)
  36. 绝不重新定义继承而来的 non-virtual 函数
  37. 绝不重新定义继承而来的缺省参数值,因为缺省参数值是静态绑定(statically bound),而 virtual 函数却是动态绑定(dynamically bound)
  38. 通过复合塑模 has-a(有一个)或 “根据某物实现出”(在应用域(application domain),复合意味 has-a(有一个);在实现域(implementation domain),复合意味着 is-implemented-in-terms-of(根据某物实现出))
  39. 明智而审慎地使用 private 继承(private 继承意味着 is-implemented-in-terms-of(根据某物实现出),尽可能使用复合,当 derived class 需要访问 protected base class 的成员,或需要重新定义继承而来的时候 virtual 函数,或需要 empty base 最优化时,才使用 private 继承)
  40. 明智而审慎地使用多重继承(多继承比单一继承复杂,可能导致新的歧义性,以及对 virtual 继承的需要,但确有正当用途,如 “public 继承某个 interface class” 和 “private 继承某个协助实现的 class”;virtual 继承可解决多继承下菱形继承的二义性问题,但会增加大小、速度、初始化及赋值的复杂度等等成本)
  41. 了解隐式接口和编译期多态(class 和 templates 都支持接口(interfaces)和多态(polymorphism);class 的接口是以签名为中心的显式的(explicit),多态则是通过 virtual 函数发生于运行期;template 的接口是奠基于有效表达式的隐式的(implicit),多态则是通过 template 具现化和函数重载解析(function overloading resolution)发生于编译期)
  42. 了解 typename 的双重意义(声明 template 类型参数是,前缀关键字 class 和 typename 的意义完全相同;请使用关键字 typename 标识嵌套从属类型名称,但不得在基类列(base class lists)或成员初值列(member initialization list)内以它作为 base class 修饰符)
  43. 学习处理模板化基类内的名称(可在 derived class templates 内通过 this-> 指涉 base class templates 内的成员名称,或藉由一个明白写出的 “base class 资格修饰符” 完成)
  44. 将与参数无关的代码抽离 templates(因类型模板参数(non-type template parameters)而造成代码膨胀往往可以通过函数参数或 class 成员变量替换 template 参数来消除;因类型参数(type parameters)而造成的代码膨胀往往可以通过让带有完全相同二进制表述(binary representations)的实现类型(instantiation types)共享实现码)
  45. 运用成员函数模板接受所有兼容类型(请使用成员函数模板(member function templates)生成 “可接受所有兼容类型” 的函数;声明 member templates 用于 “泛化 copy 构造” 或 “泛化 assignment 操作” 时还需要声明正常的 copy 构造函数和 copy assignment 操作符)
  46. 需要类型转换时请为模板定义非成员函数(当我们编写一个 class template,而它所提供之 “与此 template 相关的” 函数支持 “所有参数之隐式类型转换” 时,请将那些函数定义为 “class template 内部的 friend 函数”)
  47. 请使用 traits classes 表现类型信息(traits classes 通过 templates 和 “templates 特化” 使得 “类型相关信息” 在编译期可用,通过重载技术(overloading)实现在编译期对类型执行 if...else 测试)
  48. 认识 template 元编程(模板元编程(TMP,template metaprogramming)可将工作由运行期移往编译期,因此得以实现早期错误侦测和更高的执行效率;TMP 可被用来生成 “给予政策选择组合”(based on combinations of policy choices)的客户定制代码,也可用来避免生成对某些特殊类型并不适合的代码)
  49. 了解 new-handler 的行为(set_new_handler 允许客户指定一个在内存分配无法获得满足时被调用的函数;nothrow new 是一个颇具局限的工具,因为它只适用于内存分配(operator new),后继的构造函数调用还是可能抛出异常)
  50. 了解 new 和 delete 的合理替换时机(为了检测运用错误、收集动态分配内存之使用统计信息、增加分配和归还速度、降低缺省内存管理器带来的空间额外开销、弥补缺省分配器中的非最佳齐位、将相关对象成簇集中、获得非传统的行为)
  51. 编写 new 和 delete 时需固守常规(operator new 应该内涵一个无穷循环,并在其中尝试分配内存,如果它无法满足内存需求,就应该调用 new-handler,它也应该有能力处理 0 bytes 申请,class 专属版本则还应该处理 “比正确大小更大的(错误)申请”;operator delete 应该在收到 null 指针时不做任何事,class 专属版本则还应该处理 “比正确大小更大的(错误)申请”)
  52. 写了 placement new 也要写 placement delete(当你写一个 placement operator new,请确定也写出了对应的 placement operator delete,否则可能会发生隐微而时断时续的内存泄漏;当你声明 placement new 和 placement delete,请确定不要无意识(非故意)地遮掩了它们地正常版本)
  53. 不要轻忽编译器的警告
  54. 让自己熟悉包括 TR1 在内的标准程序库(TR1,C++ Technical Report 1,C++11 标准的草稿文件)
  55. 让自己熟悉 Boost(准标准库)

More Effective c++

  1. 仔细区别 pointers 和 references(当你知道你需要指向某个东西,而且绝不会改变指向其他东西,或是当你实现一个操作符而其语法需求无法由 pointers 达成,你就应该选择 references;任何其他时候,请采用 pointers)
  2. 最好使用 C++ 转型操作符(static_castconst_castdynamic_castreinterpret_cast
  3. 绝不要以多态(polymorphically)方式处理数组(多态(polymorphism)和指针算术不能混用;数组对象几乎总是会涉及指针的算术运算,所以数组和多态不要混用)
  4. 非必要不提供 default constructor(避免对象中的字段被无意义地初始化)
  5. 对定制的 “类型转换函数” 保持警觉(单自变量 constructors 可通过简易法(explicit 关键字)或代理类(proxy classes)来避免编译器误用;隐式类型转换操作符可改为显式的 member function 来避免非预期行为)
  6. 区别 increment/decrement 操作符的前置(prefix)和后置(postfix)形式(前置式累加后取出,返回一个 reference;后置式取出后累加,返回一个 const 对象;处理用户定制类型时,应该尽可能使用前置式 increment;后置式的实现应以其前置式兄弟为基础)
  7. 千万不要重载 &&|| 和 , 操作符(&& 与 || 的重载会用 “函数调用语义” 取代 “骤死式语义”;, 的重载导致不能保证左侧表达式一定比右侧表达式更早被评估)
  8. 了解各种不同意义的 new 和 delete(new operatoroperator newplacement newoperator new[]delete operatoroperator deletedestructoroperator delete[]
  9. 利用 destructors 避免泄漏资源(在 destructors 释放资源可以避免异常时的资源泄漏)
  10. 在 constructors 内阻止资源泄漏(由于 C++ 只会析构已构造完成的对象,因此在构造函数可以使用 try...catch 或者 auto_ptr(以及与之相似的 classes) 处理异常时资源泄露问题)
  11. 禁止异常流出 destructors 之外(原因:一、避免 terminate 函数在 exception 传播过程的栈展开(stack-unwinding)机制种被调用;二、协助确保 destructors 完成其应该完成的所有事情)
  12. 了解 “抛出一个 exception” 与 “传递一个参数” 或 “调用一个虚函数” 之间的差异(第一,exception objects 总是会被复制(by pointer 除外),如果以 by value 方式捕捉甚至被复制两次,而传递给函数参数的对象则不一定得复制;第二,“被抛出成为 exceptions” 的对象,其被允许的类型转换动作比 “被传递到函数去” 的对象少;第三,catch 子句以其 “出现于源代码的顺序” 被编译器检验对比,其中第一个匹配成功者便执行,而调用一个虚函数,被选中执行的是那个 “与对象类型最佳吻合” 的函数)
  13. 以 by reference 方式捕获 exceptions(可避免对象删除问题、exception objects 的切割问题,可保留捕捉标准 exceptions 的能力,可约束 exception object 需要复制的次数)
  14. 明智运用 exception specifications(exception specifications 对 “函数希望抛出什么样的 exceptions” 提供了卓越的说明;也有一些缺点,包括编译器只对它们做局部性检验而很容易不经意地违反,与可能会妨碍更上层的 exception 处理函数处理未预期的 exceptions)
  15. 了解异常处理的成本(粗略估计,如果使用 try 语句块,代码大约整体膨胀 5%-10%,执行速度亦大约下降这个数;因此请将你对 try 语句块和 exception specifications 的使用限制于非用不可的地点,并且在真正异常的情况下才抛出 exceptions)
  16. 谨记 80-20 法则(软件的整体性能几乎总是由其构成要素(代码)的一小部分决定的,可使用程序分析器(program profiler)识别出消耗资源的代码)
  17. 考虑使用 lazy evaluation(缓式评估)(可应用于:Reference Counting(引用计数)来避免非必要的对象复制、区分 operator[] 的读和写动作来做不同的事情、Lazy Fetching(缓式取出)来避免非必要的数据库读取动作、Lazy Expression Evaluation(表达式缓评估)来避免非必要的数值计算动作)
  18. 分期摊还预期的计算成本(当你必须支持某些运算而其结构几乎总是被需要,或其结果常常被多次需要的时候,over-eager evaluation(超急评估)可以改善程序效率)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值