操作系统
1.进程、线程和协程的区别和联系
进程 | 线程 | 协程 | |
定义 | 资源分配和拥有的基本单位 | 程序执行的基本单位 | 用户态的轻量级线程,线程内部调度的基本单位 |
切换情况 | 进程CPU环境(栈、寄存器、页表和文件句柄等)的保存与新调度的进程CPU环境的设置 | 保存和设置程序计数器、少量寄存器和栈的内容 | 先将寄存器上下文和栈保存,等切换回来的时候再进行恢复 |
切换者 | 操作系统 | 操作系统 | 用户 |
切换过程 | 用户态-》内核态-》用户态 | 用户态-内核态-用户态 | 用户态 |
调用栈 | 内核栈 | 内核栈 | 用户栈 |
拥有资源 | CPU资源、内存资源、文件资源和句柄等 | 程序计数器、寄存器、栈和状态字 | 拥有自己的寄存器上下文和栈 |
并发性 | 不同进程间切换实现并发 | 一个进程内部的多个线程并发执行 | 同一时间只能执行一个协程、其他协程处于休眠状态 |
系统开销 | 切换虚拟地址空间、切换内核栈和硬件上下文、CPU高速缓存失效、页表切换、开销很大 | 切换时只需保存和设置少量寄存器内容,开销很少 | 直接操作栈则基本没有内核切换的开销,可不加锁的访问全局变量,上下文切换非常快 |
通信 | 管道、消息队列、共享内存、 | 线程间可直接读写进程数据段(全局变量)来进行通信 | 共享内存、消息队列 |
线程间共享的有堆、全局变量、静态变量、指针、引用、文件等,独自占有栈。所以线程共享同一进程的内存空间。
1.一个进程可创建多少线程?
理论上一个进程可用的虚拟地址空间是2G,默认情况下一个线程大小为1MB,所以理论上一个进程最多可创建2048个线程。
一个进程可创建的线程数由可用虚拟地址空间和线程的栈的大小共同决定。
进程结构由以下部分组成:代码段、堆栈段、数据段。代码段是静态的二进制代码,多个程序共享。父进程创建完子进程后,父、子进程除了pid基本一致,共享全部数据。子进程通过写时拷贝和父进程共享数据。
进程地址空间:32位进程的地址空间都是4G,但用户态下只能访问低3G地址空间,只有加入内核态后,才可访问3G~4G的地址空间。
2.进程调度算法
- 先来先服务(FCFS)
- 短作业优先(SJF)
- 最短剩余时间优先(Shortest Remaining Time Next,SRTN)
- 时间片轮转
- 优先级调度
- 多级反馈队列
3.Linux下进程间通信方式
- 管道:一种特殊的文件,仅存在内存中。无名管道,半双工,只在具有亲缘关系的进程间用;有名管道,先进先出的通信方式
- 共享内存:最快的IPC方式,与信号量配合使用,进行进程同步。
- 消息队列:消息的链表,存放在内核中。独立于读写进程存在,读进程可根据消息类型有选择地接收消息。
- 套接字
- 信号和信号量
4.Linux下的同步机制
POSIX信号量:进程、线程都可用
POSIX互斥锁+条件变量:只可用于线程同步
5.进程间的状态切换
就绪状态(ready)等待调度
运行状态(running)
阻塞状态(waiting)等待资源
就绪和运行可以相互转换,其他都是单向转换,阻塞状态是缺少需要的资源而由运行状态转换过来。
6.操作系统对内存管理时需要做什么?
- 负责内存空间的分配与回收
- 提供某种技术从逻辑上对内存空间进行扩充
- 提供地址转换功能,负责程序的逻辑地址与物理地址的转换
- 提供内存保护功能,保证各进程在各自存储空间内运行,互不干扰
7.线程通信方法
信号
锁机制:互斥锁、读写锁、自旋锁
条件变量
信号量
8.虚拟内存的目的?
让物理内存扩充成更大的逻辑内存,让程序获得更多的可用内存。为了更好地管理内存,操作系统将内存抽象成地址空间。每个程序拥有自己的地址空间,这个地址空间被分割成很多块,每一块称为一页。这些页被映射到物理内存,当程序引用到不在物理内存中的页时,由硬件执行必要的映射,将缺失的部分装入物理内存并重新执行失败的指令。
9.典型的锁
读写锁:多个读者可同时读;写必须互斥(只允许一个写,写读不可同时进行);写优于读
互斥锁
条件变量
自旋锁
计算机网络
传输层数据叫做段(segments);网络层传输的数据称作包(packages);数据链路层传输的数据叫做帧(frames);物理层传输的数据称为比特流(bits)。
1.HTTP请求的完整过程
域名解析DNS->发起TCP的三次握手-》建立TCP连接后发起HTTP请求-》服务器响应HTTP请求,浏览器得到HTML代码-》浏览器解析HTML代码,请求HTML代码中的资源(图片)-》浏览器对页面进行渲染。
2.DNS的原理
主机域名转换为IP地址,属于应用层协议,使用UDP传输(速度快,不需3次握手,传输内容不超过512字节)。
浏览器缓存-》系统缓存-》路由器缓存-》IPS服务器缓存-》根域名服务器缓存;顶级域名服务器缓存、、主域名服务器缓存。递归向上查询。
3.HTTP的长连接和短连接
HTTP/1.0中默认使用短连接,客户端和服务端每进行一次HTTP操作,就建立一次连接,任务结束就中断连接。三种请求方法:GET、POST、HEAD
HTTP/1.1默认使用长连接。新增6种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE、CONNECT方法
4.TCP粘包/拆包
一个完整的业务被TCP拆分成多个包发送,也可以把多个小的包封装成一个大的数据包发送,即拆包和粘包。
原因:
- 应用程序写入数据的字节大小大于套接字发送缓冲区的大小;
- 进行MSS大小的TCP分段(MSS=TCP报文段长度-TCP首部长度);
- 以太网的payload大于MTU进行IP分片
解决方案:
- 消息定长
- 在包尾部增加回车或空格符等特殊字符进行分割
- 将消息分为消息头和消息尾
- 使用其他复杂协议,如RTMP协议
5.TCP四大拥塞控制算法
慢启动;拥塞避免;拥塞发生;快速恢复
6.流量控制原理
接收方通过TCP头窗口字段告知发送方本方可接收的最大数据量,流量控制是点对点的。
TCP是双工协议、双方可以同时通信、发送方和接收方各自维护一个发送窗和接收窗。
7.TCP协议如何保证可靠传输
- 确认和重传:接收方收到报文会确认、发送方发送一段时间没有收到确认就会重传。
- 数据校验:TCP报文头有校验和。
- 数据合理分片和排序:TCP会按最大传输单元MTU合理分片,接收方会缓存未按序到达的数据,重新排序后交给应用层。
- 流量控制:接收方通过滑动窗口,提示发送方降低发送速率。滑动窗口的大小意味着接收方还有多大的缓冲区可以用于接收数据。
- 拥塞控制:当网络拥塞时,通过拥塞窗口,减少数据的发送。
8.IP路由
IP协议的一个核心任务是数据报的路由,决定发送数据报到目标机器的路径。当IP模块收到来自数据链路层的IP数据报时,首先对数据报头部做CRC校验,无误后分析头部信息。
分析数据报的IP地址,若是本机的IP地址,接着解析数据报中的协议字段,并派发给上层应用。否则查找本机的路由表,若找到匹配的IP地址,将数据报转发到相应的端口。(检查数据报头部的TTL值,若为0,则丢弃数据报,防止陷入循环;转发后将TTL减1)
IP路由机制
- 查找路由表中和数据报中的目的IP地址完全匹配的主机IP地址,若找到,就使用该路由项,否则转步骤2;
- 查找路由表中和数据报中的目的IP地址有相同网路ID的网络IP地址,若找到,使用该路由项,否则转步骤3;
- 选择默认路由项,通常意味着数据报的下一跳是网关。
数据库
1.MySQL如何执行一条SQL?具体步骤?
- 客户端请求
- 连接器(验证用户身份,给予权限)
- 查询缓存(存在缓存则直接返回,不存在继续执行)
- 分析器(对SQL进行词法分析和语法分析)
- 优化器(对执行的SQL优化选择最优的执行方案)
- 执行器(执行时先看用户是否有执行权限,有才使用这个引擎提供的接口)
- 去引擎层获取数据返回
2.MySQL的组成
有服务层和引擎层。服务层包括连接器、查询缓存、分析器、优化器、执行器。存储引擎层负责数据的存储和提取,架构是插件式,支持InnoDB、MyISAM、Memoty等多个存储引擎。最常用的是InnoDB
3.Drop、Delete、Truncate的区别
delete删除表的部分数据行,执行delete后,用户需要提交(commit)或回滚(rollback)来执行删除或撤销删除。
truncate删除表中所有数据,操作无法回滚,比delete块。
drop从数据库中删除表,所有数据行、索引和权限也会被删除,无法回滚。
因此,不需要表时用drop;想删除部分数据行是用delete;保留表但删除所有数据时用truncate。
4.数据库索引采用B+树而不是B树的原因
- 局部性原理
- 方便扫库
- 查找效率更稳定
B+树只遍历叶节点就可实现整棵树的遍历,数据库中基于范围的查询是十分普遍的;(局部性原理),B树只可中序遍历所有节点,效率太低。
B+树方便扫库,只需直接从叶子节点挨个扫一遍就可完成扫库;而B树必须用中序遍历的方法按序扫库。
B+树查找效率更稳定,从根节点到所有叶节点的路径等长,B树中间节点也可能有数据,不够稳定。
B+树的内部节点没有数据,更小,同一盘块所能容纳的关键字数量越多。
5.MySQL索引主要使用的两种数据结构是什么?
- 哈希索引,底层数据结构是哈希表,需求为单条记录查询,查询性能最快。
- BTree索引,MySQL的BTree索引使用的是B树中的B+树,将索引值按一定的算法,存入一个树形的数据结构中(二叉树),每次查询都从树的root开始,依次遍历node,获取leaf。