☆操作系统
☆基础
- ★★★ 进程与线程的本质区别、以及各自的使用场景
- 进程是资源分配的基本单位,线程是调度的基本单位。
- 同一进程的线程,对共享,栈私有,共享地址空间。
- 线程间可以直接通信,进程间需要经过IPC。
- 多进程:编程容易,不用考虑锁和同步资源问题,容错性强,数据隔离
- 多线程:创建快,数据共享,切换快,非均质服务
- ★★★ 进程调度算法的特点以及使用场景
- FCFS(先来先服务):有利于长作业,不利于短作业,非抢占
- SJF(短作业优先):估计最短运行时间调度,长作业可能会被饿死,非抢占
- SRTN(最短剩余时间优先):最短作业优先的抢占式,按剩余运行时间调度
- ★★★ 进程通信方法的特点以及使用场景★
- 管道(无名管道):半双工,父子、兄弟进程间使用,pipe()
- FIFO(命名管道、有名管道):客户服务器间应用,fifo()
- 消息队列:独立于读写进程、避免了同步阻塞、有选择性接受
- 信号量:控制多进程访问共享数据
- 共享存储:速度最快
- 套接字:不同机器间进程通信
- ★★★ 死锁问题
原因:系统资源不足、进程运行推进的顺序不合适、资源分配不当等
- 必要条件:互斥、请求保持、不可抢占、环路等待
- 检测:- 每种类型一个资源:对访问过的节点进行标记 - 每种类型多个资源:资源总量进行计算
- 解决:剥夺资源、撤销进程、利用抢占、回滚、杀死进程恢复
- 预防:破坏四个必要条件
- 避免:安全状态检测、银行家算法
数据库中解决死锁:
- 按同一顺序访问对象。
- 避免事务中的用户交互。
- 保持事务简短并在一个批处理中。
- 使用低隔离级别。
- 使用绑定连接。
- 用存储过程查出引起死锁的进程和SQL语句。
- ★★★ 虚拟内存的作用,分页系统实现虚拟内存原理
- 让物理内存扩充成更大的逻辑内存,从而让程序获得更多的可用内存
- 分页地址映射、内存管理单元(MMU)
- 虚拟地址:页面号、偏移量
- ★★★ 页面置换算法的原理
- 最近最久未使用(LRU)非常重要
- 最近未使用(NRU):使用链表实现,在Redis上作为缓存置换算法
- 先进先出(FIFO)
- 第二次机会:读写时R = 1,替换时R若为1,则改为0放在尾端,不换出
- 时钟
- ★★★ 比较分页与分段的区别
- 分页透明、分段需要程序员划分
- 分页为一维地址空间、分段为二维
- 页大小不变、段大小可变
- 分页:虚拟内存,分段:程序和数据在逻辑上独立、有利于共享和保护
- ★★★ 分析静态链接的不足,以及动态链接的特点★
- 不足:静态库更新时那么整个程序都要重新进行链接,对于 printf 这种标准函数库,如果每个程序都要有代码,这会极大浪费资源
- 动态:给定的文件系统中一个库只有一个文件,一个副本可以被不同的正在运行的进程共享
- ★★☆ 常见进程同步问题★
- 哲学家进餐
- 读者-写者
- ★★☆ 协程的作用
- 协程是单进程单线程的超越函数的调度机制,它通过一定的调度手段进行调度
- 可重入能力,类似与函数
- 用来控制过程输出状态的那些输入状态的管理工作
-
协程的优势,协程的轻量性体现在哪里?
- 用户自己控制切换时机,不需要陷入内核态
- 没有线程切换的开销
- 不需要多线程锁机制,只要一个线程
-
线程与堆栈的关系
- 栈是线程私有的(局部变量、操作数、动态链接)
- 堆是线程共享的(对象的实例和数组)
- 方法区也是线程共享的
-
★☆☆ 进程状态
- 就绪:经调度算法可以转为运行
- 运行:cpu时间片用完后转为就绪
- 阻塞:缺少资源
-
★☆☆ 线程实现的方式(Java),优劣
- 继承Thread类,并重写其run()方法
- 实现Runnable接口,并实现其run()方法
- 实现Callable接口,并实现其call()方法
- 实现接口会更好一些:Java 不支持多重继承,因此继承了 Thread 类就无法继承其它类,但是可以实现多个接口
☆Linux
- ★★★ 硬链接与软链接的区别
- 硬链接:文件1 和 文件2 直接指向内存
ln file1 file2
- 软链接:指向另外一个文件
ln -s file1 file2
- ★★★ 僵尸进程与孤儿进程的区别,从 SIGCHLD 分析产生僵尸进程的原因
- 僵尸进程:子进程退出后,父进程未调用wait()waitpid(),进程描述符未释放
- 孤儿进程:父进程退出,子进程运行,会被init进程收养,没有危害
- 杀死僵尸进程的父进程,僵尸进程变为孤儿进程
- ★★☆ 文件系统的原理,特别是 inode 和 block。数据恢复原理
- inode:一个文件占用一个 inode,记录文件的属性,同时记录此文件的内容所在的 block 编号;
- block:记录文件的内容,文件太大时,会占用多个 block
- superblock:记录文件系统的整体信息,包括 inode 和 block 的总量、使用量、剩余量,以及文件系统的格式与相关信息等
- block bitmap:记录 block 是否被使用的位图
- Linux启动时调用那些文件★
- 开启电源 --> BIOS开机自检 --> 引导程序lilo或grub --> 内核的引导(kernel boot)–> 执行init(rc.sysinit、rc)–> mingetty(建立终端) --> shell
- /etc/profile --> ~/.bash_profile --> ~/.bash_login --> ~/.profile
-
什么是linux的daemon进程?和一般进程有什么区别?
- 守护进程,随系统启动和关闭,不与客户端交互,独立于终端。
- 使用ps axj命令查看进程时,其终端名(TTY)显示为?,ID显示为-1
-
通过free命令查看内存时,看到的buffer和cache各表示什么含义?
- 使用内存、剩余内存
- Cache:缓存区,是高速缓存,是文件系统的cache
- Buffer:缓冲区,传输数据,是块设备的读写缓冲区
-
apache和nginx这两个web服务器有哪些区别?
- apache 是同步多进程模型,一个连接对应一个进程,而 nginx 是异步的,多个连接(万级别)可以对应一个进程
- nginx轻量级,处理静态文件好,
- apache 稳定,处理动态请求有优势
☆网络
☆基础
- ★★★ 各层的作用,TCP/IP 协议的特点
-
应用层 :为特定应用程序提供数据传输服务,例如 HTTP、DNS 等协议。数据单位为报文。
-
传输层 :为进程提供通用数据传输服务。由于应用层协议很多,定义通用的传输层协议就可以支持不断增多的应用层协议。运输层包括两种协议:传输控制协议 TCP,提供面向连接、可靠的数据传输服务,数据单位为报文段;用户数据报协议 UDP,提供无连接、尽最大努力的数据传输服务,数据单位为用户数据报。TCP 主要提供完整性服务,UDP 主要提供及时性服务。
-
网络层 :为主机提供数据传输服务。而传输层协议是为主机中的进程提供数据传输服务。网络层把传输层传递下来的报文段或者用户数据报封装成分组。
-
数据链路层 :网络层针对的还是主机之间的数据传输服务,而主机之间可以有很多链路,链路层协议就是为同一链路的主机提供数据传输服务。数据链路层把网络层传下来的分组封装成帧。
-
物理层 :考虑的是怎样在传输媒体上传输数据比特流,而不是指具体的传输媒体。物理层的作用是尽可能屏蔽传输媒体和通信手段的差异,使数据链路层感觉不到这些差异
-
表示层 :数据压缩、加密以及数据描述,这使得应用程序不必关心在各台主机中数据内部格式不同的问题。
-
会话层 :建立及管理会话。
-
TCP/IP : 只有四层,数据链路层和物理层合并为网络接口层
-
★★★ 三次握手以及四次挥手具体过程、原因、TIME_WAIT
-
★★★ 可靠传输原理,并设计可靠 UDP 协议
- TCP 可靠传输:超时重传
- 可靠 UDP 协议:应用层实现确认机制、重传机制、窗口确认机制:RUDP、RTP、UDT
- ★★★ UDP 与 TCP 比较,分析上层协议应该使用 UDP 还是 TCP
- UDP:无连接、尽最大可能交付、一对一、多对多、多对一
- TCP:面向连接、可靠交付、全双工、流量拥塞控制、字节流、一对一、确认机制、重传机制、滑动窗口
-
★★☆ 路由选择协议及特点
- RIP:距离向量、15跳、固定时间交换路由表、3分钟超时
- OSPF:开放最短路径优先、洪泛发送信息、链路状态发生变化时发送信息
- BGP:比较好不是最佳,TCP,发言人制度
-
★★☆ DNS 的端口号;TCP 还是 UDP;作为缓存、负载均衡
- 端口:53,UDP
- 使用TCP的情况:数据大于512字节,区域传送
- ★★☆ TCP 拥塞控制、四种方法、理解具体原理★
- 慢开始,拥塞避免,快重传,快恢复
- 防止过多的数据注入到网络当中,这样可以使网络中的路由器或链路不致过载
-
★★☆ 浏览器访问页面(输入网址后发生了什么)
- DHCP配置主机信息(可略过)
- DHCP 请求报文,UDP,255.255.255.255:67,0.0.0.0:68
- DHCP 服务器: DHCP ACK 报文:IP 地址、DNS 服务器的 IP 地址、默认网关路由器的 IP 地址和子网掩码
- ARP 解析 MAC 地址(获取路由网关地址)
- DNS解析域名
- HTTP 请求页面
- DHCP配置主机信息(可略过)
-
★★☆ 集线器、交换机、路由器的作用,以及所属的层次
- 集线器:物理层、比特
- 交换机:链路层、自学习、按mac地址存储转发
- 路由器:网络层、IP地址转发
-
★★☆ 以太网的特点,以及帧结构
- 星型结构
- 帧结构:目的地址、源地址、类型、IP数据报、FCS
☆HTTP
-
★★★ GET 与 POST 比较:作用、参数、安全性、幂等性、可缓存
- POST 主要用来传输数据,而 GET 主要用来获取资源
- GET参数:ASCII码
- GET安全、幂等,POST不安全不幂等
- GET、HEAD可缓存,PUT、DELETE、POST不可缓存
-
★★★ Cookie 作用、安全性问题、和 Session 的比较
- 保存状态信息(会话管理、行为跟踪),cookie最大4kb
- 作用域:默认为当前文档的主机
- Cookie可利用Session存在服务器端
- Cookie 只能存储 ASCII 码字符串,而 Session 则可以存储任何类型的数据
-
★★★ 长连接与短连接原理以及使用场景,流水线
- 长连接:建立一个TCP多次进行HTTP通信
- 流水线:同一条长连接上连续发出请求
-
★★★ HTTP 存在的安全性问题,以及 HTTPs 的加密、认证和完整性保护作用
- 明文进行通信,不验证身份,无法证明报文的完整性
- 使用了SSL隧道进行通信
- 使用非对称密钥加密方式,传输对称密钥加密方式所需要的 Secret Key
- 获取到 Secret Key 后,再使用对称密钥加密方式进行通信
- SSL 提供报文摘要功能来进行完整性保护、MD5
-
★★☆ 缓存 的Cache-Control 字段、Expires 和 max-age 的区别、ETag 验证原理
- 缓解服务器压力,降低客户端获取资源的延迟
- no-store:禁止,no-cache:强制确认,private:私有,public:公共
- ETag : 资源唯一标识
-
★★★ HTTP/1.1 的特性
- 默认是长连接
- 支持流水线
- 支持同时打开多个 TCP 连接
- 支持虚拟主机
- 新增状态码 100:表示正常
- 支持分块传输编码
- 新增缓存处理指令 max-age
-
★★☆ HTTP/1.x 的缺陷,以及 HTTP/2 的特点
- 缺陷:多个连接才能实现并发和缩短延迟、不会压缩请求和响应首部浪费流量、没有优先级支持
- 二进制帧分层、服务端推送、首部压缩
-
★★☆ HTTP 与 FTP 的比较
-
★☆☆ 状态码
-
http协议中的keeplive是做什么的?它的适应场景是什么?
- 让多个http请求共享一个Tcp连接,避免每个http新建tcp连接
- 定时发送心跳包
-
http请求有多少种?
- 8种
- opions:返回服务器针对特定资源所支持的HTML请求方法、get、post、put:向指定资源位置上上传其最新内容
- head:查看某个页面的状态、delete、trace:回显服务器收到的请求、connect
-
查看linux系统中tcp连接的状态和连接数量统计
netstat -an | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
-
bash shell 里
$0.$?.$$
各表示什么含义- $$ Shell本身的PID(ProcessID)
- $! Shell最后运行的后台Process的PID
- $? 最后运行的命令的结束代码(返回值)
- $# 是传给脚本的参数个数
- $0 是脚本本身的名字
- $1 是传递给该shell脚本的第一个参数
- $2 是传递给该shell脚本的第二个参数
- $@ 是传给脚本的所有参数的列表
☆Socket
-
★★★ select、poll、epoll 的原理、比较、以及使用场景;epoll 的水平触发与边缘触发
- 都是多路复用的具体实现
- select 会修改描述符,而 poll 不会
- select 的描述符类型使用数组实现
- poll 提供了更多的事件类型,并且对描述符的重复利用上比 select 高
- 如果一个线程对某个描述符调用了 select 或者 poll,另一个线程关闭了该描述符,会导致调用结果不确定
- select 和 poll 速度都比较慢
-
★★☆ 五种 IO 模型的特点以及比较
- 阻塞式I/O:阻塞应用,内核缓存–>应用缓存(数据复制),复制完返回
- 非阻塞式I/O:进程调用、返回错误码、继续执行、不断询问io(轮询),CPU利用率低
- I/O复用:单进程处理多IO,无进程创建切换,系统开销小
- 信号驱动I/O:进程使用 sigaction 系统调用,内核立即返回,进程继续执行,数据到达时内核向应用发送 SIGIO 信号,进程调用 recvfrom 复制数据,CPU利用率高
- 异步I/O:进程执行 aio_read 系统调用会立即返回,进程继续执行,不被阻塞,内核在操作完成后向进程发送信号
- 比较
- 同步 I/O:将数据从内核缓冲区复制到应用进程缓冲区的阶段(第二阶段),应用进程会阻塞
- 异步 I/O:第二阶段应用进程不会阻塞
-
多路复用
-
Java NIO
☆数据库
- 数据库范式
- 第一范式:属性的原子性
- 第二范式:属性完全依赖于主键
- 第三范式:一个数据库表中不包含已经在其它表中包含的非主键关键字信息。
☆SQL
-
★★☆ 手写 SQL 语句,特别是连接查询与分组查询
-
★★☆ 连接查询与子查询的比较
-
★★☆ drop、delete、truncate 比较
- 作用
- DELETE 删除表中 WHERE 语句指定的数据。
- TRUNCATE 清空表,相当于删除表中的所有数据。
- DROP 删除表结构
- 事务
- DELETE 会被放到日志中以便进行回滚;
- TRUNCATE 和 DROP 立即生效,不会放到日志中,也就不支持回滚。
- 删除空间
- DELETE 不会减少表和索引占用的空间;
- TRUNCATE 会将表和索引占用的空间恢复到初始值;
- DROP 会将表和索引占用的空间释放。
- 耗时
- DELETE < TRUNCATE < DROP
- 作用
-
★★☆ 视图的作用,以及何时能更新视图
- 虚拟表
- 简化复杂操作、保证数据安全性
- 更改数据格式和表示
-
★☆☆ 理解存储过程、触发器等作用
- 存储过程可以看成是对一系列 SQL 操作的批处理
- 优点:封装、提高安全性,代码复用,高性能
- 赋值用 select into ,每次只能给一个变量赋值,不支持集合的操作
- 触发器会在某个表执行以下语句时而自动执行:DELETE、INSERT、UPDATE
- 必须指定在语句执行之前还是之后自动执行(前:BEFORE,后:AFTER)
- 存储过程可以看成是对一系列 SQL 操作的批处理
☆MySQL
-
MySQL主键
- 其值能唯一地标识表中的每一行
-
事务
- 用于处理操作量大,复杂度高的数据
- 只有InnoDB支持事务
- ACID
☆其他
- new和malloc区别
- malloc和new都是在堆上开辟内存的
- malloc只负责开辟内存,没有初始化功能
- new不但开辟内存,还可以进行初始化
- malloc是函数,开辟内存需要传入字节数
- malloc开辟内存失败返回NULL,new开辟内存失败抛出bad_alloc类型的异常
- malloc开辟的内存永远是通过free来释放的;而new单个元素内存,用的是delete,如果new[]数组,用的是delete[]来释放内存
- malloc开辟内存只有一种方式,而new有四种分别是普通的new(内存开辟失败抛出bad_alloc异常), nothrow版本的new,const new以及定位new
- 闭包
- 闭包函数:声明一个在函数中的函数
- 内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。
- 特点:
- 外部函数访问内部变量成为可能
- 局部变量常驻内存
- 避免使用全局变量、防止全局变量污染
- 会造成内存泄漏
- 每次外部函数执行的时候,外部函数的引用地址不同,都会重新创建一个新的地址
☆python
- 如何在Python中实现多线程?
-
答: Python有一个multi-threading包,但是如果你想让multi-thread加速你的代码,那么使用它通常不是一个好主意。
-
Python有一个名为Global Interpreter Lock(GIL)的结构。 GIL确保只有一个“线程”可以在任何时候执行。一个线程获取GIL,做一点工作,然后将GIL传递到下一个线程。
-
这种情况很快发生,因此对于人眼看来,您的线程似乎并行执行,但它们实际上只是轮流使用相同的CPU核心。
-
所有这些GIL传递都增加了执行的开销。这意味着如果您想让代码运行得更快,那么使用线程包通常不是一个好主意。
- 这是什么意思: *args,**kwargs?我们为什么要用呢?
我们用*args
当我们不确定将多少个参数传递给函数时,或者我们是否要将存储的列表或参数元组传递给函数时。**kwargs
当我们不知道将多少关键字参数传递给函数时,或者它可以用于将字典的值作为关键字参数传递时使用。标识符args和kwargs是一个约定,你也可以使用*bob
和**billy
,但这不是明智之举.
-
计算出从你生日之日起到今天一共过了多少天?(python、go、shell均可)
-
逆序输出偶数的平方 [1,2,3,4,5,6,7,8,9]
1 | #列表切片 |
☆面向对象
☆思想
- ★★★ 面向对象三大特性
- 继承:父类指向子类时为向上转型
- 封装:减少耦合、减轻维护负担、提高可重用性、减少重构风险
- 多态:编译时多态与运行时多态
- 运行时多态:继承、覆盖(重写)、向上转型
- ★☆☆ 设计原则
- 单一责任原则SRP
- 开放封闭原则OCP
- 李氏替换原则LSP
- 接口分离原则ISP
- 依赖倒置原则DIP
☆设计模式
☆Java
☆基础
- 基本类型与包装类型
- byte/8 char/16 short/16 int/32 float/32 double/64 long/64 boolean/~
- 缓存池、new Integer(123) 与 Integer.valueOf(123) 的区别
- Integer 缓存池的大小默认为 -128~127
- String不可变的原因、好处
- final 声明、不可被继承
- Java8 中使用 char 存储、Java9 后使用byte数组存储
- 可以缓存hash值、String Pool的需要、提高安全性(参数不变)、线程安全
- 注意:StringBuffer可变、线程安全,StringBuilder可变、线程不安全
- 参数传递的方式、类型转换、switch
- 值传递、地址值
- 不能隐式向下转型、
+=
或者++
运算符会执行隐式类型转换 - switch 不支持 long
- Java类的初始化顺序
- 静态成员和
static块
-> 普通成员和非static
块 -> 构造函数 - 父类静态 -> 子类静态 -> 父类普通 -> 父类构造 -> 子类普通 -> 子类构造
- 静态成员和
equal()
与==
的区别- 对于基本类型,== 判断两个值是否相等,基本类型没有 equals() 方法
- 对于引用类型,== 判断两个变量是否引用同一个对象,而 equals() 判断引用的对象是否等价
- 在覆盖 equals() 方法时应当总是覆盖 hashCode() 方法,保证等价的两个对象哈希值也相等
- clone()、浅拷贝、深拷贝
- clone() 是 Object 的 protected 方法、需要显式重写
- 浅拷贝对象和原始对象的引用类型引用同一个对象
- 深拷贝对象和原始对象的引用类型引用不同对象
- clone替代:拷贝构造函数、拷贝工厂
- 反射的优缺点
- 定义:允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性
- 优点:可扩展性、类浏览器和可视化开发环境、调试器和测试工具
- 缺点:性能开销高、安全限制、内部暴露
- Java与c++的区别
- Java面向对象,c++兼容c、可以面向过程
- Java跨平台
- Java无指针、自动垃圾回收
- Java不支持多重继承,c++可以
- Java不支持操作符重载
- c++可以使用goto
- 泛形相关
- 允许在定义类、接口、方法时使用类型形参,在声明变量、创建对象、调用方法时再传入实际类型参数
- 好处:编译时检查类型安全、隐式强制转换
- 工作方式:通过类型擦除实现
- 限定通配符: extends T> super T> 非限定通配符:>