文章目录

  • C++
  • 数据结构
  • 数据库
  • 计算机网络
  • 计算机操作系统
  • Linux
  • Web

C++

1. 虚函数和纯虚函数
定义一个函数为虚函数,不代表函数为不被实现的函数;定义他为虚函数是为了允许用基类的指针来调用子类的这个函数;定义一个函数为纯虚函数,才代表函数没有被实现;定义纯虚函数是为了实现一个接口,起到一个规范的作用,规范继承这个类的程序员必须实现这个函数。

  1. 虚函数和纯虚函数可以定义在同一个类(class)中,含有纯虚函数的类被称为抽象类(abstract class),而只含有虚函数的类(class)不能被称为抽象类(abstract class)。
  2. 虚函数可以被直接使用,也可以被子类(sub class)重载以后以多态的形式调用,而纯虚函数必须在子类(sub class)中实现该函数才可以使用,因为纯虚函数在基类(base class)只有声明而没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加 =0:。
  3. 虚函数和纯虚函数都可以在子类(sub class)中被重载,以多态的形式被调用。
  4. 虚函数和纯虚函数通常存在于抽象基类(abstract base class -ABC)之中,被继承的子类重载,目的是提供一个统一的接口。
  5. 虚函数的定义形式:virtual {method body}
      纯虚函数的定义形式:virtual void funtion1()=0
    在虚函数和纯虚函数的定义中不能有static标识符,原因很简单,被static修饰的函数在编译时候要求前期bind,然而虚函数却是动态绑定(run-time bind),而且被两者修饰的函数生命周期(life recycle)也不一样。
  6. 虚函数必须实现,如果不实现,编译器将报错,错误提示为:
    error LNK****: unresolved external symbol “public: virtual void __thiscall
    ClassName::virtualFunctionName(void)”
  7. 对于虚函数来说,父类和子类都有各自的版本。由多态方式调用的时候动态绑定。
  8. 实现了纯虚函数的子类,该纯虚函数在子类中就编程了虚函数,子类的子类即孙子类可以覆盖该虚函数,由多态方式调用的时候动态绑定。
  9. 虚函数是C++中用于实现多态(polymorphism)的机制。核心理念就是通过基类访问派生类定义的函数
  10. 多态性指相同对象收到不同消息或不同对象收到相同消息时产生不同的实现动作。C++支持两种多态性:编译时多态性,运行时多态性。
    a.编译时多态性:通过重载函数实现
    b 运行时多态性:通过虚函数实现。
  11. 如果一个类中含有纯虚函数,那么任何试图对该类进行实例化的语句都将导致错误的产生,因为抽象基类(ABC)是不能被直接调用的。必须被子类继承重载以后,根据要求调用其子类的方法。
    多态
    虚函数

2. C/C++程序内存的各种变量存储区域和各个区域详解
1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域(RW), 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域(ZI)。 - 程序结束后有系统释放
4、文字常量区 —常量字符串就是放在这里的。 程序结束后由系统释放 (RO)
5、程序代码区—存放函数体的二进制代码。 (RO)

3. new/delete与malloc/free的区别与联系
1、new/delete是C++的操作符,而malloc/free是C中的函数。
2、new做两件事,一是分配内存,二是调用类的构造函数;同样,delete会调用类的析构函数和释放内存。而malloc和free只是分配和释放内存。
3、new建立的是一个对象,而malloc分配的是一块内存;new建立的对象可以用成员函数访问,不要直接访问它的地址空间;malloc分配的是一块内存区域,用指针访问,可以在里面移动指针;new出来的指针是带有类型信息的,而malloc返回的是void指针。
4、new/delete是保留字,不需要头文件支持;malloc/free需要头文件库函数支持。

4. map、set分别干什么的?
map和set都是C++的关联容器,其底层实现都是红黑树(RB-Tree)。
由于 map 和set所开放的各种操作接口,RB-tree 也都提供了,所以几乎所有的 map 和set的操作行为,都只是转调 RB-tree 的操作行为。
map和set区别在于:
map中的元素是key-value(关键字—值)对:关键字起到索引的作用,值则表示与索引相关联的数据;Set与之相对就是关键字的简单集合,set中每个元素只包含一个关键字。
set的迭代器是const的,不允许修改元素的值;map允许修改value,但不允许修改key。其原因是因为map和set是根据关键字排序来保证其有序性的,如果允许修改key的话,那么首先需要删除该键,然后调节平衡,再插入修改后的键值,调节平衡,如此一来,严重破坏了map和set的结构,导致iterator失效,不知道应该指向改变前的位置,还是指向改变后的位置。所以STL中将set的迭代器设置成const,不允许修改迭代器的值;而map的迭代器则不允许修改key值,允许修改value值。
map支持下标操作,set不支持下标操作。map可以用key做下标,map的下标运算符[]将关键码作为下标去执行查找,如果关键码不存在,则插入一个具有该关键码和mapped_type类型默认值的元素至map中,因此下标运算符[ ]在map应用中需要慎用,const_map不能用,只希望确定某一个关键值是否存在而不希望插入元素时也不应该使用,mapped_type类型没有默认值也不应该使用。如果find能解决需要,尽可能用find。

5. 数组和链表的区别和联系
1.数组:
数组是将元素在内存中连续存放,由于每个元素占用内存相同,可以通过下标迅速访问数组中任何元素。但是如果要在数组中增加一个元素,需要移动大量元素,在内存中空出一个元素的空间,然后将要增加的元素放在其中。同样的道理,如果想删除一个元素,同样需要移动大量元素去填掉被移动的元素。如果应用需要快速访问数据,很少插入和删除元素,就应该用数组。
2.链表:
链表中的元素在内存中不是顺序存储的,而是通过存在元素中的指针联系到一起,每个结点包括两个部分:一个是存储数据元素 的数据域,另一个是存储下一个结点地址的 指针。如果要访问链表中一个元素,需要从第一个元素始,一直找到需要的元素位置。但是增加和删除一个元素对于链表数据结构就非常简单了,只要修改元素中的指针就可以了。如果应用需要经常插入和删除元素你就需要用链表。
3.区别:
(1)存储位置上:
数组逻辑上相邻的元素在物理存储位置上也相邻,而链表不一定;
(2)存储空间上:
链表存放的内存空间可以是连续的,也可以是不连续的,数组则是连续的一段内存空间。一般情况下存放相同多的数据数组占用较小的内存,而链表还需要存放其前驱和后继的空间。
(3)长度的可变性:
链表的长度是按实际需要可以伸缩的,而数组的长度是在定义时要给定的,如果存放的数据个数超过了数组的初始大小,则会出现溢出现象。
(4)按序号查找时,数组可以随机访问,时间复杂度为O(1),而链表不支持随机访问,平均需要O(n); 
(5)按值查找时,若数组无序,数组和链表时间复杂度均为O(1),但是当数组有序时,可以采用折半查找将时间复杂度降为O(logn); 
(6)插入和删除时,数组平均需要移动n/2个元素,而链表只需修改指针即可; 
(7)空间分配方面:
数组在静态存储分配情形下,存储元素数量受限制,动态存储分配情形下,虽然存储空间可以扩充,但需要移动大量元素,导致操作效率降低,而且如果内存中没有更大块连续存储空间将导致分配失败; 即数组从栈中分配空间,,对于程序员方便快速,但自由度小。
链表存储的节点空间只在需要的时候申请分配,只要内存中有空间就可以分配,操作比较灵活高效;即链表从堆中分配空间, 自由度大但申请管理比较麻烦。

6. const 与 #define的比较
C++ 语言可以用const来定义常量,也可以用 #define来定义常量。但是前者比后者有更多的优点:
(1) const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误(边际效应)。
(2) 有些集成化的调试工具可以对const常量进行调试,但是不能对宏常量进行调试。
如果有一个常量,是定义为宏常量好还是定义为const常量(应该是定义为const常量,宏常量的话符号会被替换掉不易查错。使用const定义,既可以保证值的唯一性,又便于调试,同时还可以对数据类型进行检查,借助编译器来减少错误的发生

7. STL之vector中push_back的时间复杂度分析
vector是STL中的一种序列式容器,采用的数据结构为线性连续空间,它以两个迭代器 start 和 finish 分别指向配置得来的连续空间中目前已被使用的范围,并以迭代器end_of_storage 指向整块连续空间(含备用空间)的尾端
我们在使用 vector 时​,最常使用的操作恐怕就是插入操作了(push_back),那么当执行该操作时,该函数都做了哪些工作呢?
该函数首先检查是否还有备用空间,如果有就直接在备用空间上构造元素,并调整迭代器 finish,使 vector变大。如果没有备用空间了,就扩充空间,重新配置、移动数据,释放原空间。​
其中​判断是否有备用空间,就是判断 finish是否与 end_of_storage 相等.如果
finish != end_of_storage,说明还有备用空间,否则已无备用空间。
当执行 push_back 操作,该 vector 需要分配更多空间时,它的容量(capacity)会增大到原来的 m 倍。​现在我们来均摊分析方法来计算 push_back 操作的时间复杂度。
假定有 n 个元素,倍增因子为 m。那么完成这 n 个元素往一个 vector 中的push_back​操作,需要重新分配内存的次数大约为 logm(n),第 i 次重新分配将会导致复制 m^i (也就是当前的vector.size() 大小)个旧空间中元素,因此 n 次 push_back操作所花费的总时间约为 nxm/(m - 1):
时间复杂度计算。很明显这是一个等比数列.那么 n 个元素,n 次操作,每一次操作需要花费时间为 m / (m - 1),这是一个常量。
所以,我们采用均摊分析的方法可知,vector 中 push_back 操作的时间复杂度为常量时间.​
在STL中,vector的每次扩容都是2倍,也就是m=2.这样,n次总的时间约为n*2/(2-1) = 2n;那么每一操作要花的时间就是2,因此是常量级。

8. string的实际数据存放在哪?vector呢?
string的内存肯定是在堆上的,string内部自己维护一个申请和释放的指针,你外部应用是不用关心空间的申请,它内部会从堆上申请控件,析构时释放空间。如果一直在栈上,肯定会爆掉。
vector这个对象存在栈中,然后栈中有指向vector所存数据的地址,数据保存在堆中。

9. vector和list的区别
vector和数组类似,拥有一段连续的内存空间,并且起始地址不变。vector和数组类似,拥有一段连续的内存空间,并且起始地址不变。
因此,它能够高效地进行随机存取,时间复杂度是O(1)。
但是,因为其内存空间是连续的,所以在进行插入和删除操作时,会造成内存块的拷贝,因此时间复杂度为O(n)。
另外,当数组内存空间不够时,会重新申请一块内动空间并进行内存拷贝。
list是由双向链表实现的,因此内存空间是不连续的。
其只能通过指针访问数据,所以list的随机存取效率很低,时间复杂度为O(n)。
不过由于链表自身的特点,能够进行高效的插入和删除。
vector和list对于迭代器的支持不同。
相同点在于,vector< int >::iterator和list< int >::iterator都重载了 “++ ”操作。
而不同点在于,在vector中,iterator支持 ”+“、”+=“,”<"等操作。而list中则不支持。

10. new和malloc的区别
new/delete是C++关键字,需要编译器支持。malloc/free是库函数,需要头文件支持。
使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算。而malloc则需要显式地指出所需内存的尺寸
new会先调用operator new函数,申请足够的内存(通常底层使用malloc实现)。然后调用类型的构造函数,初始化成员变量,最后返回自定义类型指针。delete先调用析构函数,然后调用operator delete函数释放内存(通常底层使用free实现)。
C++允许重载new/delete操作符,特别的,布局new的就不需要为对象分配内存,而是指定了一个地址作为内存起始区域,new在这段内存上为对象调用构造函数完成初始化工作,并返回此地址。而malloc不允许重载。
new操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。而堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。自由存储区不等于堆,如上所述,布局new就可以不位于堆中。

11. hash_map和map的区别在哪里
构造函数。hash_map需要hash函数,等于函数;map只需要比较函数(小于函数).
存储结构。hash_map采用hash表存储,map一般采用红黑树(RB Tree)实现。因此其memory数据结构是不一样的。
什么时候需要用hash_map,什么时候需要用map?
总体来说,hash_map 查找速度会比map快,而且查找速度基本和数据数据量大小,属于常数级别;而map的查找速度是log(n)级别。并不一定常数就比log(n)小,hash还有hash函数的耗时,明白了吧,如果你考虑效率,特别是在元素达到一定数量级时,考虑考虑hash_map。但若你对内存使用特别严格,希望程序尽可能少消耗内存,那么一定要小心,hash_map可能会让你陷入尴尬,特别是当你的hash_map对象特别多时,你就更无法控制了,而且hash_map的构造速度较慢。
现在知道如何选择了吗?权衡三个因素: 查找速度, 数据量, 内存使用。

12. 未初始化的全局变量在哪个区
text段在内存中被映射为只读;
variable:优化器在用到这个变量时必须每次都小心地重新读 取这个变量的值;
data包含静态初始化的数据,所以有初值的全局变量和static变量在data区’
bss是英文Block Started by Symbol的简称,通常是指用来存放程序中未初始化的全局变量的一块内存区域,在程序载入时由内核清0。BSS段属于静态内存分配。

13. 数内局部变量内如果一个变量不对它进行初始化,是不是输出就会变成一个随机值
若为全局变量,一般系统会初始化为0;
若为局部变量,会得到一个随机值;
建议使用时对其初始化。

14. 为什么构造函数不能为虚函数, 为什么析构函数可以为虚函数,什么情况下需要将析构函数定义为虚函数?
虚函数对应一个vtable,这大家都知道,可是这个vtable其实是存储在对象的内存空间的。问题出来了,如果构造函数是虚的,就需要通过 vtable来调用,可是对象还没有实例化,也就是内存空间还没有,无法找到vtable,所以构造函数不能是虚函数。构造函数不需要是虚函数,也不允许是虚函数,因为创建一个对象时我们总是要明确指定对象的类型,尽管我们可能通过实验室的基类的指针或引用去访问它。但析构却不一定,我们往往通过基类的指针来销毁对象。这时候如果析构函数不是虚函数,就不能正确识别对象类型从而不能正确调用析构函数。
从实现上看,vbtl在构造函数调用后才建立,因而构造函数不可能成为虚函数

将可能会被继承的父类的析构函数设置为虚函数,可以保证当我们new一个子类,然后使用基类指针指向该子类对象,释放基类指针时可以释放掉子类的空间,防止内存泄漏。
C++默认的析构函数不是虚函数是因为虚函数需要额外的虚函数表和虚表指针,占用额外的内存。而对于不会被继承的类来说,其析构函数如果是虚函数,就会浪费内存。因此C++默认的析构函数不是虚函数,而是只有当需要当作父类时,设置为虚函数。

数据结构

1. 哈希表和红黑树的对比
权衡三个因素: 查找速度, 数据量, 内存使用,可扩展性,有序性。
hash查找速度会比RB树快,而且查找速度基本和数据量大小无关,属于常数级别;而RB树的查找速度是log(n)级别。并不一定常数就比log(n) 小,因为hash还有hash函数的耗时。当元素达到一定数量级时,考虑hash。但若你对内存使用特别严格, 希望程序尽可能少消耗内存,那么hash可能会让你陷入尴尬,特别是当你的hash对象特别多时,你就更无法控制了,而且 hash的构造速度较慢。
红黑树是有序的,Hash是无序的,根据需求来选择。
红黑树占用的内存更小(仅需要为其存在的节点分配内存),而Hash事先应该分配足够的内存存储散列表,即使有些槽可能弃用
红黑树查找和删除的时间复杂度都是O(logn),Hash查找和删除的时间复杂度都是O(1)。

2. 排序算法及其稳定性
十大经典排序算法

3. AVL树,红黑树,B树,B+树,Trie树都分别应用在哪些现实场景中?
AVL树: 最早的平衡二叉树之一。应用相对其他数据结构比较少。windows对进程地址空间的管理用到了AVL树。
红黑树: 平衡二叉树,广泛用在C++的STL中。如map和set都是用红黑树实现的。
B/B+树: 用在磁盘文件组织 数据索引和数据库索引。
Trie树(字典树): 用在统计和排序大量字符串,如自动机。

4. 先序,中序,后序,层次遍历
先序:根节点->左子树->右子树
中序:左子树->根节点->右子树
后序:左子树->右子树->根节点
以上是栈,层次遍历用队列。

数据库

1. 为什么数据库用b+树不用b树和红黑树
首先说红黑树为什么不行:
1.红黑树必须存在内存里的,数据库表太大了,存不进去。
2.即使你找到了把红黑树存进硬盘的方法,红黑树查找一个节点最多要查logN层,每一层都是一个内存页(虽然你只是想找一个节点,但硬盘必须一次读一个页。。),那么一共logN次IO,伤不起阿!
先讲下b树和b+树的区别:
b树的所有节点都是数据节点,但b+树只有叶子节点是数据节点,非叶子(内部)节点只起导向作用,不存储实际数据。
b+树的所有数据节点都在最下层(叶子节点层),相邻节点有链表相连。
再说b树为什么不如b+树:
1.b树的内部节点都是存储实际数据的,比如一个节点是一个页4096字节,其中每条数据128字节,那么一个节点只能存32个数据项,那么对应的孩子节点数最多为33个,这显然不够用。而b+树内部节点只作为导向作用,只存一个整数就可以,4096/4=1024个数据项。这样b+树的每个节点的孩子数更多,整个树的高度就更低,大大增加查询效率。
2.b+树的叶子节点有链表相连,适合范围查询,因为相邻页直接读取就好了。但b树做不到这一点。
B树

B+树

2. 索引不宜太多
索引虽然是为提高查询的速度而设计, 它对insert/delete/update有负面影响,
但使用不当, 同样会降低查询的速度。索引太多,文件过大。还有第二点没答出来,更新数据的时候索引也要更新,耗时.

计算机网络

1.TCP和UDP的最完整的区别
TCP的优点: 可靠,稳定 TCP的可靠体现在TCP在传递数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、拥塞控制机制,在数据传完后,还会断开连接用来节约系统资源。 TCP的缺点: 慢,效率低,占用系统资源高,易被攻击 TCP在传递数据之前,要先建连接,这会消耗时间,而且在数据传递时,确认机制、重传机制、拥塞控制机制等都会消耗大量的时间而且要在每台设备上维护所有的传输连接,事实上,每个连接都会占用系统的CPU、内存等硬件资源。 而且,因为TCP有确认机制、三次握手机制,这些也导致TCP容易被人利用,实现DOS、DDOS、CC等攻击。

UDP的优点: 快,比TCP稍安全 UDP没有TCP的握手、确认、窗口、重传、拥塞控制等机制,UDP是一个无状态的传输协议,所以它在传递数据时非常快。没有TCP的这些机制,UDP较TCP被攻击者利用的漏洞就要少一些。但UDP也是无法避免攻击的,比如:UDP Flood攻击…… UDP的缺点: 不可靠,不稳定 因为UDP没有TCP那些可靠的机制,在数据传递时,如果网络质量不好,就会很容易丢包。 基于上面的优缺点,那么: 什么时候应该使用TCP: 当对网络通讯质量有要求的时候,比如:整个数据要准确无误的传递给对方,这往往用于一些要求可靠的应用,比如HTTP、HTTPS、FTP等传输文件的协议,POP、SMTP等邮件传输的协议。 在日常生活中,常见使用TCP协议的应用如下: 浏览器,用的HTTP FlashFXP,用的FTP Outlook,用的POP、SMTP Putty,用的Telnet、SSH QQ文件传输 ………… 什么时候应该使用UDP: 当对网络通讯质量要求不高的时候,要求网络通讯速度能尽量的快,这时就可以使用UDP。 比如,日常生活中,常见使用UDP协议的应用如下: QQ语音 QQ视频 TFTP ……
有些应用场景对可靠性要求不高会用到UPD,比如长视频,要求速率

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

1.1. 为什么视频用UDP
tcp需要进bai行三次握手,du建立会话需要时间,tcp在网络拥塞的情况zhi下会进行tcp全局dao同步,根据网络带宽调整tcp滑动窗口大小,引起tcp传输速度下降,甚至有可能会导致tcp报文没有带宽可用,导致tcp饿死,而视频传输对带宽的需求比较大,对时延要求比较高,对丢包率要求不是那么高,udp是面向无连接的传输协议,不需要进行三次握手,也没有tcp的滑动窗口,报文也比tcp小,正好满足了对视频传输的要求。
明显,当数据传输的性能必须让位于数据传输的完整性、可控制性和可靠性时,TCP协议是当然的选择。当强调传输性能而不是传输的完整性时,如:音频和多媒体应用,UDP是最好的选择。在数据传输时间很短,以至于此前的连接过程成为整个流量主体的情况下,UDP也是一个好的选择,如:DNS交换。把 SNMP建立在UDP上的部分原因是设计者认为当发生网络阻塞时,UDP较低的开销使其有更好的机会去传送管理数据。

TCP UDP
是否连接 面向连接 面向非连接
传输可靠性 可靠 不可靠
应用场合 少量数据 传输大量数据
速度

2.TCP还是UDP,网络游戏应该用哪种协议
1.根据各个论坛大家的经验,用检测工具检测,流行的大型网络游戏用TCP和UDP的都有。也有的是client发送给server用TCP,server发给client用UDP(大航海时代)
2.普遍的推荐是,实时性非常强的游戏(FPS游戏如CS)才需要用UDP,因为要尽量减少延迟,TCP特有的可靠处理机制导致丢包重发会有较大的延迟。否则用TCP,例如MMORPG游戏用TCP,棋牌类游戏更不必说就是用TCP。
3.著名开源网络引擎RakNet用的是UDP实现,但它同时注明了UDP有很多的麻烦,RakNet用了很多方法来克服这些麻烦。http://gafferongames.com/networking-for-game-programmers/udp-vs-tcp/这篇文章讲得不错,说明了为什么实时性强的网络游戏(CS等)需要用UDP而不是TCP。
4.但UDP协议因为太过基础,如果不是购买商业级网络引擎而是自行开发,会在这上面花费很大的人力并且还不一定达到低延迟的效果,在研发周期短压力大情况下更是如此。如果这样那还不如TCP,简单稳定,干脆直接,毕竟TCP是经过了周密设计和多年考验。对玩家来说,偶尔的延迟或许比较讨厌,但总掉线或出错可就是难以忍受了。

3. OSI七层模型和TCP/IP五层模型
第7层应用层—直接对应用程序提供服务,应用程序可以变化,但要包括电子消息传输,应用程序,如FTP,SMTP,HTTP
第6层表示层—格式化数据,以便为应用程序提供通用接口。这可以包括加密服务,编码方式,图像编解码、URL字段传输编码
第5层会话层—在两个节点之间建立端连接。此服务包括建立连接是以全双工还是以半双工的方式进行设置,尽管可以在层4中处理双工方式,建立会话,SESSION认证、断点续传
第4层传输层—常规数据递送-面向连接或无连接。包括全双工或半双工、流控制和错误恢复服务 ,进程和端口
第3层网络层—本层通过寻址来建立两个节点之间的连接,它包括通过互连网络来路由和中继数据,路由器,防火墙、多层交换机
第2层数据链路层—在此层将数据分帧,并处理流控制。本层指定拓扑结构并提供硬件寻址,网卡,网桥,交换机
第1层物理层—原始比特流的传输电子信号传输和硬件接口数据发送时,从第七层传到第一层,接受方则相反。中继器,集线器、网线、HUB

4.ping下面是基于哪个协议
使用的是ICMP协议,是“Internet Control Message Protocol”(Internet控制消息协议)的缩写,是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。
它是用来检查网络是否通畅或者网络连接速度的命令。它所利用的原理是这样的:利用网络上机器IP地址的唯一性,给目标IP地址发送一个数据包,再要求对方返回一个同样大小的数据包来确定两台网络机器是否连接相通,时延是多少。

5. Http和Https的区别(面试常考题)
HTTP和HTTPS的区别

计算机操作系统

1. 线程间通信的几种实现方式
同步和互斥
当有多个线程的时候,经常需要去同步这些线程以访问同一个数据或资源。例如,假设有一个程序,其中一个线程用于把文件读到内存,而另一个线程用于统计文件中的字符数。当然,在把整个文件调入内存之前,统计它的计数是没有意义的。但是,由于每个操作都有自己的线程,操作系统会把两个线程当作是互不相干的任务分别执行,这样就可能在没有把整个文件装入内存时统计字数。为解决此问题,你必须使两个线程同步工作。

所谓同步,是指在不同进程之间的若干程序片断,它们的运行必须严格按照规定的某种先后次序来运行,这种先后次序依赖于要完成的特定的任务。如果用对资源的访问来定义的话,同步是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源。

所谓互斥,是指散布在不同进程之间的若干程序片断,当某个进程运行其中一个程序片段时,其它进程就不能运行它们之中的任一程序片段,只能等到该进程运行完这个程序片段后才可以运行。如果用对资源的访问来定义的话,互斥某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。

多线程同步和互斥有几种实现方法
线程间的同步方法大体可分为两类:用户模式和内核模式。顾名思义,内核模式就是指利用系统内核对象的单一性来进行同步,使用时需要切换内核态与用户态,而用户模式就是不需要切换到内核态,只在用户态完成操作。
用户模式下的方法有:原子操作(例如一个单一的全局变量),临界区。
内核模式下的方法有:事件,信号量,互斥量。
1、临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。
2、互斥量:为协调共同对一个共享资源的单独访问而设计的。
3、信号量:为控制一个具有有限数量用户资源而设计。
4、事 件:用来通知线程有一些事件已发生,从而启动后继任务的开始。

2. 进程间通信的几种实现方式
(1)管道(pipe)及有名管道(named pipe):管道可用于具有亲缘关系的父子进程间的通信,有名管道除了具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。
(2)信号(signal):信号是在软件层次上对中断机制的一种模拟,它是比较复杂的通信方式,用于通知进程有某事件发生,一个进程收到一个信号与处理器收到一个中断请求效果上可以说是一致的。
(3)消息队列(message queue):消息队列是消息的链接表,它克服了上两种通信方式中信号量有限的缺点,具有写权限得进程可以按照一定得规则向消息队列中添加新信息;对消息队列有读权限得进程则可以从消息队列中读取信息。
(4)共享内存(shared memory):可以说这是最有用的进程间通信方式。它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据得更新。这种方式需要依靠某种同步操作,如互斥锁和信号量等。
(5)信号量(semaphore):主要作为进程之间及同一种进程的不同线程之间得同步和互斥手段。
(6)套接字(socket):这是一种更为一般得进程间通信机制,它可用于网络中不同机器之间的进程间通信,应用非常广泛。

3. 协程了解
协程是一种线程工作的机制。正常情况下,一个线程处理一个函数或者是一个程序,但是协程是在处理函数的时候,这个函数还有调用其他函数,也就是还有子函数,所以协程在处理的时候使用这一个线程去处理这两个函数,在处理的时候呢,并不是按顺序执行完一个函数再去执行另一个函数,而是执行A函数到一半的时候又去执行函数,这两个函数相互交替执行,这么个机制,叫做协程。
之前说过多线程在执行的时候,是抢夺资源式的执行任务,在读取同一个变量的时候可能会发生冲突,所以为了防止发生冲突,我们用到了线程锁。通过队列,一个线程写信息,一个线程读消息,线程锁控制线程的等待和队列的读写。
但是协程不会发生这种冲突,因为只有一个线程在进行读取数据的操作,不存在同时读写冲突。所以协程是控制自身,在子程序之间进行切换
协程的特点在于是一个线程执行,那和多线程比,协程有何优势?
最大的优势就是协程极高的执行效率。因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。
第二大优势就是不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多

因为协程是一个线程执行,那怎么利用多核CPU呢?最简单的方法是多进程+协程,既充分利用多核,又充分发挥协程的高效率,可获得极高的性能。
Python对协程的支持是通过generator实现的。
在generator中,我们不但可以通过for循环来迭代,还可以不断调用next()函数获取由yield语句返回的下一个值。
但是Python的yield不但可以返回一个值,它还可以接收调用者发出的参数。

4. 进程和线程的区别
1.一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。线程依赖于进程而存在。
2.进程在执行过程中拥有独立的内存单元,而多个线程共享进程的内存。(资源分配给进程,同一进程的所有线程共享该进程的所有资源。同一进程中的多个线程共享代码段(代码和常量),数据段(全局变量和静态变量),扩展段(堆存储)。但是每个线程拥有自己的栈段,栈段又叫运行时段,用来存放所有局部变量和临时变量。)
3.进程是资源分配的最小单位,线程是CPU调度的最小单位
4.系统开销: 由于在创建或撤消进程时,系统都要为之分配或回收资源,如内存空间、I/o设备等。因此,操作系统所付出的开销将显著地大于在创建或撤消线程时的开销。类似地,在进行进程切换时,涉及到整个当前进程CPU环境的保存以及新被调度运行的进程的CPU环境的设置。而线程切换只须保存和设置少量寄存器的内容,并不涉及存储器管理方面的操作。可见,进程切换的开销也远大于线程切换的开销。
5.通信:由于同一进程中的多个线程具有相同的地址空间,致使它们之间的同步和通信的实现,也变得比较容易。进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。在有的系统中,线程的切换、同步和通信都无须操作系统内核的干预
6.进程编程调试简单可靠性高,但是创建销毁开销大;线程正相反,开销小,切换速度快,但是编程调试相对复杂。
7.进程间不会相互影响 ;线程一个线程挂掉将导致整个进程挂掉
8.进程适应于多核、多机分布;线程适用于多核

5. 调度算法
1、先来先服务(FCFS)/先进先出(FIFO)调度算法
2、短作业优先调度算法(SJF)
3、高优先权调度算法
4、高响应比优先调度算法
5、简单的时间片轮转法(RR—Round Robin)
调度算法详解

Linux

1. gcc/g++编译文件过程
.c文件 -----> 预处理后的.i文件
内容: 头文件的展开,宏定义的替换,备注的去除

gcc  -E hello.c -o hello.i

.i文件----->汇编语言的.s文件
内容:预处理后的文件转换为汇编语言代码

gcc -S hello.i -o hello.s

.s文件----->二进制文件.o
内容:汇编文件编译为二进制文件

gcc -c hello.s -o hello.o

生成执行文件
内容:组合函数库等的代码到目标文件中。

gcc hello.o -o hello

1.1 gcc链接的作用
链接主要是为了解决多个文件之间符号引用的问题。编译时编译器只对单个文件进行处理,如果该文件里面需要引用到其他文件中符号(例如全局变量或者某个函数库中的函数),那么这时在这个文件中该符号的地址是没法确定的,只能等链接器把所有的目标文件连接到一起才能确定最终的地址,最终生成可执行文件。
当所有目标文件都生成之后,gcc就在内部调用链接器ld完成链接工作。在链接阶段,所有的目标文件被安排在可执行文件的恰当位置。

2. 静态库和动态库的作用

静态库:之所以成为【静态库】,是因为在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中。因此对应的链接方式称为静态链接。
试想一下,静态库与汇编生成的目标文件一起链接为可执行文件,那么静态库必定跟.o文件格式相似。其实一个静态库可以简单看成是一组目标文件(.o/.obj文件)的集合,即很多目标文件经过压缩打包后形成的一个文件。静态库特点总结:
l 静态库对函数库的链接是放在编译时期完成的。
l 程序在运行时与函数库再无瓜葛,移植方便。
l 浪费空间和资源,因为所有相关的目标文件与牵涉到的函数库被链接合成一个可执行文件。
动态库:l 空间浪费是静态库的一个问题。
l 另一个问题是静态库对程序的更新、部署和发布页会带来麻烦。如果静态库liba.lib更新了,所以使用它的应用程序都需要重新编译、发布给用户(对于玩家来说,可能是一个很小的改动,却导致整个程序重新下载,全量更新)。
动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题。动态库在程序运行是才被载入,也解决了静态库对程序的更新、部署和发布页会带来麻烦。用户只需要更新动态库即可,增量更新。
动态库特点总结:
l 动态库把对一些库函数的链接载入推迟到程序运行的时期。
l 可以实现进程之间的资源共享。(因此动态库也称为共享库)
l 将一些程序升级变得简单。
l 甚至可以真正做到链接载入完全由程序员在程序代码中控制(显示调用)。
Window与Linux执行文件格式不同,在创建动态库的时候有一些差异。
l 在Windows系统下的执行文件格式是PE格式,动态库需要一个DllMain函数做出初始化的入口,通常在导出函数的声明时需要有_declspec(dllexport)关键字。
l Linux下gcc编译的执行文件默认是ELF格式,不需要初始化入口,亦不需要函数做特别的声明,编写比较方便。
与创建静态库不同的是,不需要打包工具(ar、lib.exe),直接使用编译器即可创建动态库。

3. 用户态和内核态
内核态:cpu可以访问内存的所有数据,包括外围设备,例如硬盘,网卡,cpu也可以将自己从一个程序切换到另一个程序。
用户态:只能受限的访问内存,且不允许访问外围设备,占用cpu的能力被剥夺,cpu资源可以被其他程序获取。
为什么要有用户态和内核态?
由于需要限制不同的程序之间的访问能力, 防止他们获取别的程序的内存数据, 或者获取外围设备的数据, 并发送到网络, CPU划分出两个权限等级 – 用户态和内核态。

Web

1. GET和POST两种基本请求方法的区别

GET、POST

牛客C++面经
牛客C++面试题
leetcode面试题

offer--刷题之路(持续更新)相关推荐

  1. 力扣牛客每日刷题(Python解法持续更新)

    力扣牛客每日刷题(持续更新) 初试结束第15天, 之前简单的处理了部分毕设方面的任务, 对接下来的学习做了个简单的规划 决定每天开始刷几道力扣题提高一下算法的理解,不能让之前学的数据结构都忘记了 每道 ...

  2. LeetCode(力扣) 刷题注意事项 持续更新 ~ ~

    文章目录 刷题无止境,那就让自己快乐一点 刷哪的题 抱前辈大腿 没有思路的题目 提交前检查代码 提交后 可以做的更好 在哪儿看题解 不要试图从题解的代码中理解思路 LeetCode的使用技巧 一次可以 ...

  3. leetcode刷题总结(持续更新)

    1.关于递归与迭代 递归的性能低但是代码直观,改成迭代后子结构不变 二叉树的迭代实现? 2.动态规划 关于最大值最小值这种最值问题,一般都可以通过动态规划的方法进行判断,某些存在性问题也可以用动态规划 ...

  4. python金融量化初体验——2020年“大湾区杯”金融数学建模比赛A题《大湾区指数增强策略》刷题总结(持续更新中)

    目录 1.前言 2.准备工作 (1)题目分析: 提供的数据集 问题 3.解题思路: (1)第一问解题思路 4.代码实现 (1)第一题部分代码 1.前言 之前和男朋友一起学完了数据挖掘的相关框架,决定要 ...

  5. 刷题回顾(持续更新)

    文章目录 misc 图片隐写 流量 密码 脚本 压缩包加密 图片隐写 音频类隐写 web 1,使用burpsuite进行POST需要二部曲: 2,变量覆盖与MD5 3,http 4,信息泄露思路 知识 ...

  6. 【LeetCode 剑指offer刷题】树题6:28 对称二叉树(101. Symmetric Tree)

    [LeetCode & 剑指offer 刷题笔记]目录(持续更新中...) 101. Symmetric Tree /**  * Definition for a binary tree no ...

  7. 【LeetCode 剑指offer刷题】数组题2:57 有序数组中和为s的两个数(167 Two Sum II - Input array is sorted)...

    [LeetCode & 剑指offer 刷题笔记]目录(持续更新中...) 57 有序数组中和为s的两个数 题目描述 输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是 ...

  8. 【LeetCode 剑指offer刷题】字符串题6:67 把字符串转成整数

    [LeetCode & 剑指offer 刷题笔记]目录(持续更新中...) 67 把字符串转成整数 题目描述 将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数. 数值为0或者字符 ...

  9. 【LeetCode 剑指offer刷题】树题16:Kth Smallest Element in a BST

    [LeetCode & 剑指offer 刷题笔记]目录(持续更新中...) Kth Smallest Element in a BST Given a binary search tree, ...

  10. 【LeetCode 剑指offer刷题】回溯法与暴力枚举法题6:Number of Islands

    [LeetCode & 剑指offer 刷题笔记]目录(持续更新中...) Number of Islands Given a 2d grid map of '1's (land) and ' ...

最新文章

  1. 关于XGMII/XLGMII/CGMII
  2. 我的家庭私有云计划-13
  3. ELK安装配置,日志展示
  4. list_for_each引起的问题
  5. JSP的三六九四七(三大指令、六大标签、九大内置对象、四大作用域、七个动作指令)
  6. print($arr,true)的参数true表示将$arr的值返会,而不是打印
  7. 找高清壁纸,没有那么麻烦,高图网帮你搞定!
  8. 论文阅读:Deep Image Matting
  9. cdr 表格自动填充文字_操作基础知识Word文字编辑
  10. 用计算机名共享打印机不能打印,共享打印机无法打印怎么办解决教程
  11. 我的世界逆时空服务器怎么注册密码,我的世界1.7.10服务器逆时空
  12. header标签为什么不能改变背景颜色呢?
  13. 不到一周我开发出了属于自己的知识共享平台
  14. CMP SUB 区别
  15. android 扫描手机内存和SD卡,获取手机的视频、音频文件。把获取不到的文件扫描出来
  16. 记录一下自己爬虎牙LOL主播的爬虫思路
  17. 【转帖】lmbench的简单使用
  18. Task01:熟悉新闻推荐系统的基本流程(项目结构)
  19. Quartus (Quartus Prime 18.1)的安装及仿真步骤
  20. 学习post抓包最好用的抓包工具

热门文章

  1. Python与医疗图像3
  2. Android之ListView自带的布局simple_list_item
  3. 华为2018实习面试+状态总结
  4. 交换机原理_交换机工作原理解析
  5. 计算机网络笔记17 分类的IP地址
  6. string 析构崩溃 assign
  7. 前端搜索关键字突出展示
  8. android源码大全 IOS游戏源代码打包下载 小游戏|视频教程 微信小程序源码带后台全套|公众号平台
  9. 股票软件开发总体方案
  10. 职场上这四件事,越早知道越好