C++ 面试题总结

  1. 正向代理和反向代理
    正向代理代理客户端,反向代理代理服务器
  2. http和https的区别?
    (1)http是超文本传输协议,明文传输,https是具有安全性ssl加密传输协议
    (2)http默认端口80,https默认端口443
    (3)https需要申请证书,一般需要一定费用
    (4)http链接无状态,https是ssl+http构成的可进行加密传输,安装认证的网络协议。
    (5)https会增加网络交互消耗,加载页面会增加50%的延时
  3. nginx的常用功能
    (1)负载均衡
    nginx内置负载均衡策略主要有三种:hash,权重hash,轮训
    并支持负载均衡策略扩展
    (2)反向代理
    (3)正向代理
    (4)web缓存
    (5)http服务器静态页面
  4. Http协议结构
    请求格式:
    这里写图片描述
    响应格式:
    这里写图片描述
  5. linux下进程间通信方式
    (1)管道
    (2)有名管道
    (3)信号量
    (4)消息队列
    (5)共享内存
    (6)socket
  6. 线程间同步方式
    (1)互斥量
    (2)读写锁
    (3)条件变量

  7. epoll和poll/select的区别
    poll/select:
    (1)每次使用都要把fd从用户态拷贝到内核态。
    (2)每次有时间发生或则超时,都要遍历所有的文件描述符。
    (3)支持文件描述符的数量太少,1024。
    (4)只能工作在LT模式
    epoll:
    针对poll/select的三个缺点,epoll有以下优点
    (1)整个过程只在epoll_ctl中新增fd时,才会拷贝fd信息到内核,也就是整个过程只会往内核态拷贝一次信息。
    (2)epoll只会返回有事件就绪的fd的链表。
    (3)epoll没有文件描述符数量限制,他所支持的是系统最大支持的文件描述数量。
    (4)不仅能工作在LT模式,而且还支持ET高效模式,并且支持EPOLLONESHOT事件(对于注册了该事件的描述符,操作系统最多出发其上的一个事件:可读、可写或异常事件,保证一个线程在处理该fd的事件时,其他线程不会操作改描述符)

  8. memcached和Redis的区别?
    (1)客户端交互模式
    Redis:请求/响应模式,发布/订阅模式
    memcahed:请求/响应模式
    (2)数据类型
    memcahed:字符串(二进制)
    redis:字符串,list(字符串列表),set(没有重复元素的list),map(无序key-value),sorted-set(有序的map)
    (3)redis支持事务,memcached支持cas
    (4)redis单线程,memcached多线程
    (5)redis支持持久化,memcached不支持
    (6)过期策略
    redis:懒惰机制+定期删除
    memcached:懒惰机制
    (7)内存回收
    memcached:LRU,选择最近最少使用的删除
    redis:6中如下
    noeviction:默认策略,不会删除任何数据,拒绝所有写入操作并返回客户端错误信息,此时Redis只响应读操作。
    volatitle-rlu:根据LRU算法删除设置了超时属性的键,知道腾出足够空间为止。如果没有可删除的键对象,回退到noeviction策略。
    allkeys-lru:根据LRU算法删除键,不管数据有没有设置超时属性,直到腾出足够空间为止。
    allkeys-random:随机删除所有键,知道腾出足够空间为止。
    volatitle-random:随机删除过期键,知道腾出足够空间为止。
    volatitle-ttl:根据键值对象的ttl属性,删除最近将要过期数据。如果没有,回退到noeviction策略
    (8)数据分布
    memcached:可通过客户端实现分布式数据备份
    redis:有master-slaves模式(最终一致性)和redis-cluster(可实现强一致性)

9.new/delete和malloc/free的qubie
具体参见:https://www.cnblogs.com/QG-whz/p/5140930.html
(1)申请的内存所在位置 new操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。而堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。
(2)返回类型安全性 new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换,故new是符合类型安全性的操作符。而malloc内存分配成功则是返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型。
(3)内存分配失败时的返回值 new内存分配失败时,会抛出bac_alloc异常,它不会返回NULL;malloc分配内存失败时返回NULL。
(4)是否需要指定内存大小 使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算,而malloc则需要显式地指出所需内存的尺寸。
(5)是否调用构造函数/析构函数 new/delete会调用对象的构造函数/析构函数以完成对象的构造/析构。而malloc则不会。
(6)对数组的处理 C++提供了new[]与delete[]来专门处理数组类型,而malloc/free需要自己在原始内存上做处理。
(7)new与malloc是否可以相互调用 operator new /operator delete的实现可以基于malloc,而malloc的实现不可以去调用new。
(8)是否可以被重载 opeartor new /operator delete可以被重载
(9)能够直观地重新分配内存 使用malloc分配的内存后,如果在使用过程中发现内存不足,可以使用realloc函数进行内存重新分配实现内存的扩充。realloc先判断当前的指针所指内存是否有足够的连续空间,如果有,原地扩大可分配的内存地址,并且返回原来的地址指针;如果空间不够,先按照新指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来的内存区域。new没有这样直观的配套设施来扩充内存。
10.linux内核几种锁的区别
(1)mutex 互斥锁主要用于实现内核中的互斥访问功能。对它的访问必须遵循一些规则:同一时间只能有一个任务持有互斥锁,而且只有这个任务可以对互斥锁进行解锁。互斥锁不能进行递归锁定或解锁。
(2)semaphore 信号量在创建时需要设置一个初始值,表示同时可以有几个任务可以访问该信号量保护的共享资源,初始值为1就变成互斥锁(Mutex),即同时只能有一个任务可以访问信号量保护的共享资源。一个任务要想访问共享资源,首先必须得到信号量,获取信号量的操作将把信号量的值减1,若当前信号量的值为负数,表明无法获得信号量,该任务必须挂起在该信号量的等待队列等待该信号量可用;若当前信号量的值为非负数,表示可以获得信号量,因而可以立刻访问被该信号量保护的共享资源。当任务访问完被信号量保护的共享资源后,必须释放信号量,释放信号量通过把信号量的值加1实现,如果信号量的值为非正数,表明有任务等待当前信号量,因此它也唤醒所有等待该信号量的任务。
(3)rw_semaphore 读写信号量对访问者进行了细分,或者为读者,或者为写者,读者在保持读写信号量期间只能对该读写信号量保护的共享资源进行读访问,如果一个任务除了需要读,可能还需要写,那么它必须被归类为写者,它在对共享资源访问之前必须先获得写者身份,写者在发现自己不需要写访问的情况下可以降级为读者。读写信号量同时拥有的读者数不受限制,也就说可以有任意多个读者同时拥有一个读写信号量。如果一个读写信号量当前没有被写者拥有并且也没有写者等待读者释放信号量,那么任何读者都可以成功获得该读写信号量;否则,读者必须被挂起直到写者释放该信号量。如果一个读写信号量当前没有被读者或写者拥有并且也没有写者等待该信号量,那么一个写者可以成功获得该读写信号量,否则写者将被挂起,直到没有任何访问者。因此,写者是排他性的,独占性的。
(4)Spanlock 自旋锁与互斥锁有点类似,只是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,”自旋”一词就是因此而得名。由于自旋锁使用者一般保持锁时间非常短,因此选择自旋而不是睡眠是非常必要的,自旋锁的效率远高于互斥锁。

区别: 互斥锁,信号量,读写信号量在无法得到锁时会导致进程休眠,只能在进程上下文被调用,因此,如果被保护的共享资源需要在中断上下文访问(包括底半部即中断处理句柄和顶半部即软中断),就必须使用自旋锁。
11.进程的内存布局
Linux下32位进程布局如下:
这里写图片描述
12.TCP状态变化图
这里写图片描述
13.为什么会有TIME_WAIT?
(1)保证链接可靠关闭 若处于time_wait的client发送给server确认报文段丢失的话,server将在此又一次发送FIN报文段,那么client必须处于一个可接收的状态就是time_wait而不是close状态。
(2)让迟来的报文有足够的时间识别,并被丢弃 time_wait持续的时间是2MSL,保证旧的数据能够在某个网络节点上被识别并被丢弃,MSL为报文的最大存活时间
14.怎样减少 TIME_WAIT时间?
设置socket的SO_LINGER选项

    struct linger {
        int   l_onoff;    /* linger active */
        int   l_linger;   /* how many seconds to linger for */
    };
 其中 l_onoff != 0, l_linger = 0;

猜你喜欢

转载自blog.csdn.net/u010154685/article/details/79594450
今日推荐