日常校招面试题演练8-22

问题汇总:

(1)C++ vector和list的区别?

vector底层是数组,list底层是双向链表

(2)TCP为什么2次握手不行,TCP4次挥手的过程

(3)执行main函数之前和之后做了哪些工作?

4)你在写程序的时候如果程序出现了死循环你怎么找到这个死循环?

  • 在栈区:设置栈指针
  • 在data段:初始化全局变量和静态变量
  • 在bss段:对未初始化的全局变量进行赋初值,bool是false,short,int,long 是0,指针是NULL
  • 将main函数的参数传到main函数里面

(5)B+树的时间复杂度?为什么使用B+作为数据库的索引?

如果不考虑磁盘IO读取时间,M叉二叉树的时间复杂度是log(m,n);

因为B+树能够提供稳定高效的范围扫描,他的叶子节点是相互连接的,并且是排好序的,所以是为磁盘等外存设备设计的一种索引结构,而mysql的存储是存在外存上的。

B+树作为索引结构:还具有以下优点

  • 只有叶子节点才记录数据,非叶子节点只包含索引;所有非叶子节点也就是内部节点都只保存叶子节点最小值作为索引,那么这种结构的设计意味着内存中索引节点越多,他的整个IO次数就会下降

(6)Linux命令知多少?

(7)银行转账系统中如果A转账完成之后系统出错,系统怎么解决?

(8)MySQL引擎是什么?

(9)编程题:给你一个有序整数数组,数组中的数可以是正数、负数、零,请实现一个函数,这个函数返回一个整数:返回这个数组所有数的平方值中有多少种不同的取值。

 

1. 自我介绍,聊聊项目。

2. C 与C语言内存分配的区别

C 使用new和delete操作符来完成内存的分配和释放,C语言使用malloc和free两个函数申请空间与释放。malloc只是向操作系统申请指定大小的堆空间,new操作符在申请适合对象大小的空间同时完成对象的初始化。同样free函数只是向操作系统归还指定空间,并不完成对象的析构,而delete操作符能正确调用对象的析构函数。

3. 智能指针的原理

 智能指针的原理shared_ptr可以在多个对象之间共享一个原始指针,每个复制都会使其中的引用计数 1,而智能指针对象析构时,将会使引用计数-1,当引用计数从1变为0时,表示没有任何对象在使用该指针了,因此会调用delete释放相应的空间。引用计数可以是一个整数或者结构体,多个智能指针内部共享一个引用计数的指针变量,通过指针操作该变量的值,共同维护一个正确的引用数值。

unique_ptr是唯一持有某一个原始指针,主要是通过禁止复制构造函数和使用移动构造函数实现的。移动构造函数是一个右值引用的形参,使用移动语义完成对象所有权的转移,其中并没有对原始对象进行拷贝,而只是将原始指针的所有权移动到另一个智能指针。

4. 简述下C/S模型的代码逻辑

大致说了说服务器应该先在某一个端口进行监听,等待服务器的连接。视客户端的数量,决定采用select还是epoll方式处理事件。说到这里就跳到下一个问题。

5. select和epoll的区别

select管理的套接字数量有限制,通常是1024,是使用bit位来管理的,同时系统调用和系统返回时,内核和用户空间都需要发生大量句柄的复制操作,同时对select的返回需要进行遍历操作,才能找到发生事件 的套接字。

 

epoll使用了三个阶段,epoll_create、epoll_ctl、epoll_wait,分别创建epoll句柄,添加修改删除套接字事件,等待套接字事件发生。这其中使用红黑树来管理套接字句柄集合,这样就没有数量的限制,同时epoll_ctl对事件的管理也非常高效。epoll使用的mmap(内存映射),将用户空间和内核空间映射到同一块实存,这样既有内存访问的保护性,也可以避免用户空间与内核空间的反复复制。最后在epoll_wait的调用中,epoll会将在内部记录的发生的事件从双端链表中复制到events数组中,同时返回发生事件的数组,这样可以避免用户的无效遍历。

 

6. stl模板使用过哪些?挑几个聊聊原理?他们的优缺点是什么?

vector,内部是连续空间,使用start,finish,end_of_storage几个成员变量来快速获得容量,使用大小,头元素、尾元素等信息。使用push_back、insert会造成扩容操作,具体为当前大小为n,新增大小为m,如果m n超过当前容量,就会进行扩容,扩容后大小为max(2*n, m n)。扩容的步骤为:分配新的空间、复制之前的元素、构造新的元素、释放之前的空间。同时使用vector::clear()不会释放空间,只是将其中的元素清空,若需要立即释放空间,不待变量过期,可以使用和一个空的vector进行swap操作,这样就可以将内存还给操作系统。vector优点在于能够自动申请堆空间,自动扩容,不需要手动操作,也可以保证内存的正确回收。但扩容的过程可能会导致元素大量的复制,造成效率低下,同时会使得迭代器失效,造成程序崩溃。

7. static的用法有哪些?

(1)修饰局部变量。局部变量的生存期为声明之后,直至当前代码块结束。若使用static声明,该变量将变为静态持续性,存放在静态存储区,存在于整个程序运行周期。同时保证每个进入该代码块,变量保持上一次退出时的值。

(2)修饰全局变量。会改变全局变量的链接性,使用static修饰后,全局变量由外部链接性变为内存链接性,这样其他源文件不能使用extern变量使用该变量,该变量只能在当前文件内共享访问。

(3)修饰函数。函数默认具有外部链接性,同普通全局变量一样。使用static修饰后,其他源文件不能使用extern来使用该函数。该函数为内部链接性,当前文件可访问。

(4)修饰成员变量。修饰成员变量后,该变量将不在类对象的内存布局当中,存在于静态存储区。该变量存在于类对象声明之前,即使没有任何一个类对象声明,该变量依然存在。所有的类对象共享一份实例。

(5)修饰成员函数。静态成员函数不能访问普通成员变量,只能访问静态成员变量。同时不需要通过类实例进行调用。

8. 下边代码片段中各个变量的值是什么?

int x = 2, y = 2, t = 0;
t = x--   ||   ++y;

这道题有一点难,x=1,后右边已经为真,所以不再继续往后计算,y=2,t=3

10. 链表反转
 

岗位:服务器开发工程师

 

一面:

1、你在项目在遇到过最困难的事。

2、操作系统、网络原理、编译原理。。。你最擅长哪个?(网络?)

3、浏览器的地址栏里输入一个url,点一下回车,会发生什么?

(1)浏览器怎么得到url?

HTTP请求报文中url

(2)DNS解析是发送整个url吗?

只发送域名

(3)DNS解析详细过程。

通过UDP发送域名到DNS服务器,获得对应ip地址

(4)TCP三次握手之前需要什么?

创建套接字,绑定端口

(5)ARP解析过程。

(6)ip怎么寻址?

(7)TCP第三次握手的作用是什么?

建立TCP连接

 

(9)TCP连接建立之后呢?

 

4、算法题:单链表,翻转n-m段链表。

 

5、算法题:给出有序数组和target求距离target最小的位置(min distance index)。

 

二面:

1、自我介绍。

2、重点介绍实习内容以及你做的工作内容?(详细)

3、人员权限管理模块怎么设计?

4、sql题

student:id, name, age

student_score: id,student_id, course_id, score

平均成绩前三的student_id, name

5、数据库索引的数据结构。

6、b加树和b树的区别。

7、为什么索引用b加树而不用红黑树?

8、死锁的条件。

9、如何设计来避免死锁。

10、算法题:求连续子数组最大和以及对应子数组的首尾坐标。

 

三面:

1、自我介绍。

2、重点介绍学校项目的内容。

3、介绍自己做的内容(详细)。

4、画图3个后端模块画项目流程图(详细)。

5、讲后端流程中每一部分怎么实现。

6、各部分怎么保证多线程安全。

7、Redis一致性怎么保证。

8、Redis分布式锁的原理。

9、你所了解的分布式一致性算法。

10、画图:深度学习模块项目流程图(详细)。

11、讲深度学习流程中每一部分的含义。

12、Python程序是怎样定时运行的。

13、nlp和cv数据预处理各自的流程(实验室课题不便透漏,用大方向nlp和cv代替)。

14、nlp和cv各用了什么模型。

15、结果返回的实效性问题。

16、项目有没有分布式部署。

17、如果要部署怎么部署。

18、设计题:有一个二维坐标系上有10亿个点,给定一个圆,如何快速得出哪些点在圆中(返回点集)?

 

进程线程问题总结

进程/线程/协程:

 


进程是资源分配的基本单位。

进程控制块(Process Control Block,PCB)描述进程的基本信息和运行状态,进程的创建和撤销都是由PCB来操作。

线程是独立调度的基本单位。由(程序计数器,堆栈,和一组寄存器以及一个标识符组成)

协程又称(微线程)是计算机程序的一类组件,推广了协作式多任务的子程序,允许执行被挂起与被恢复。

一个进程可以有多个线程,共享进程资源。

 

 

进程与线程的区别:

拥有资源
进程是资源分配的基本单元,但是线程不拥有资源,线程可以访问所属进程的资源
调度
线程是独立调度的基本单位,在同一进程中,线程的切换不会引起进程的切换,从一个进程中的线程切换到另一个进程中的线程时,会引起进程切换
系统开销
创建或撤销进程时,系统都要为之分配或回收资源,如内存空间、I/O设备等,所付出的开销远大于创建或撤销线程时的开销。
通信方面
线程间可以通过直接读写同一进程中的数据进行通信,进程通信需要借助IPC   
 

 

多线程和多进程:
区别:

数据共享同步

多进程:数据是分开的:共享复杂,需要IPC;同步简单
多线程:多线程共享进程数据简单,同步复杂
内存CPU

多进程:占用内存多,切换复杂,CPU利用率低
多线程:占用内存少,切换简单,CPU利用率高
创建销毁切换

    1:多进程:复杂,速度慢。

    2:所线程:简单,速度快

编程调试

    1:.多进程:编程简单调试简单

    2:多线程:编程复杂,调试复杂

可靠性

    1:多进程:进程间通信互不影响

    2:多线程:一个线程挂掉将导致整个进程挂掉

优缺点:

多进程:

优点:内存隔离,单个进程的异常不会导致其他进程的奔溃,方便调试。
缺点:进程间的操作开销比线程大
适合使用场合:目标的子功能之间的交互少
多线程:

    1 优点:提高了系统的并行性,开销小,对cup的利用率高

    2 缺点:没有内存隔离,单个线程的奔溃会导致整个应用程序的奔溃

    3 使用场合:存在大量的IO,网络等耗时操作。

 

进程状态的切换:
1.进程的三种状态:

    运行态:指该进程正在被CPU调度运行。

    就绪态:指该进程满足被cpu调度的所有条件但是并没有被调度执行。

    阻塞态:指该进程正在等待某事件的发生之后才可以继续被cpu调度运行。

三种状态之间的切换;
就绪->运行 :当操作系统的调度程序从就绪态的链表中调度一个进程时,该进程的进程状态就会被切换运行,与此同时cpu即开始进入运行状态
运行->就绪:当一个正在运行的进程的时间片到达时,cpu必须调度下一个进程,此时处于运行状态的进程被切换到就绪态,并重新进入操作系统的就绪态的进程链表。
运行->阻塞:当cpu正在运行一个进程时,该进程此时需要等待一个进程的完成才能继续运行,这时操作系统就会将该进程状态切换位阻塞状态,知道进程所需要的等待条件完成
阻塞->就绪:进程从运行态直接切换为阻塞态,当进程所需要的时间完成后,操作系统不会直接将该进程的状态切换为运行态,而是将该进程状态切换为就绪态,等待cpu的调度。
Linux操作系统的进程状态:
R运行状态:并不意味着进程一定是运行状态,也可能是在运行队列中。
S睡眠状态:进程在等待事件完成
D磁盘睡眠状态:不可终端睡眠(深度睡眠,不可被唤醒,通常发生在磁盘的写入)
T停止状态:可以通过发送SIFSTOP信号给进程来停止进程,可以发送SIGCONT信号让进程继续运行
X死亡状态:该进程是返回状态,在任务列表中看不到
Z僵尸状态:子进程退出,父进程还在运行,但是父进程没有读到子进程的退出状态,子进程成为僵尸状态
T追踪停止状态
不得不说的僵尸进程与孤儿进程
 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值