操作系统&计算机网络&数据库

操作系统 (每一点都是常考)

进程和线程的区别

  1. 进程>线程,同一进程的所有线程共享该进程的所有资源。 同时,每个线程拥有自己的栈区。
  2. 进程是资源分配的最小单位,线程是程序执行的最小单位.

补充:协程是一种用户态的轻量级线程,协程的调度完全由用户控制

进程通信的方式

首先不着急一上去就说通信方式,我们可以说一说为什么会有进程间通信???
因为我们知道进程是一个结构体,进程与进程之间是相互独立的,而有时候我们需要在两个进程之间实现数据传输、进程控制等功能(debug进程可以控制其他进程的执行),因此需要让内核给我们提供一个公共资源让两进程都能访问从而实现通信。

  1. 管道:Linux下一切皆文件这一点我们必须牢记,所以管道就是一份文件,进程A能看到进程B也能够看到,同时进程A往管道中写数据进程B就可以从另一端读数据了。
    管道的特点:1、只能承载字节流 2、半双工通信 3、生命周期随进程。
    同时还分为匿名管道和命名管道,
    匿名管道:适用于有亲缘关系的进程
    命名管道(FIFO):适用于任意进程
  2. 消息队列:说白了消息队列就是一个链表,进程A可以向队列中写数据(写满则不能写了,因为消息队列是固定的),队列中有数据了进程B就可以开始读数据了,读完了数据就不能读了(这也就能说明消息队列面向数据报)
    消息队列的特点:1、适用于任意进程 2、面向数据报 3、全双工通信(只要进程有读写权限就可以双向通信)4、生命周期随内核
  3. 共享内存:共享内存就是一块内存,我们知道内存有随机访问的优势,所以共享内存就成为了进程间通信最快的方式。具体通信原理就是映射一段能被其他进程访问的内存,这段内存由一个进程创建,但多个进程都可以访问
    共享内存的特点:1、适用于任意进程 2、全双工通信3、生命周期随内核
  4. 信号量(Semaphore):信号量准确的来说就没有通信,它用于控制多个线程对共享资源的访问,信号量的特点就是用于互斥!!!
    其实我个人觉得信号也应该属于进程间通信的一种方式,为什么呢?因为信号量用于互斥,也就是用于进程控制,而进程控制也是进程间通信的目的之一。

此处防止有坑:面试官可能会问:那全局变量进程也都能看得到,是不是也能实现通信呢?这就得说到我们的虚拟地址向物理地址映射了,全局变量在映射的时候,物理地址分布不同,那么怎么能保证两个进程看到的是同一块空间,那就无法通信了。

原文:https://blog.csdn.net/cx2479750196/article/details/81150955

补充:跨机器的进程通信有

  1. socket通信
  2. RPC:thrift,dubbo等。

孤儿进程、僵尸进程(了解)

https://www.cnblogs.com/Anker/p/3271773.html

死锁

  1. 死锁产生的原因:资源竞争、进程推进顺序不当
  2. 死锁产生的四个必要条件:
    (1)互斥条件:一个资源一次只能被一个进程使用
    (2)请求与保持条件:一个进程因请求资源而阻塞时,对已获得资源保持不放
    (3)不剥夺条件:进程获得的资源,在未完全使用完之前,不能强行剥夺
    (4)循环等待条件:若干进程之间形成一种头尾相接的环形等待资源关系

处理死锁的方法:

  1. 预防死锁(破坏必要条件234)(了解):
    (1)资源一次性分配:(破坏请求和保持条件)
    (2)可剥夺资源:(破坏不可剥夺条件)
    (3)资源有序分配法:系统给每类资源赋予一个编号,每一个进程按编号递增的顺序请求资源,释放则相反(破坏环路等待条件)
  2. 避免死锁(银行家算法)(具体算法暂时不要求记下来,只需记住一句话即可):
    一句话:
    当一个进程申请使用资源的时候,银行家算法通过先试探分配给该进程资源,然后通过安全性算法判断分配后的系统是否处于安全状态,若不安全则试探分配作废,让该进程继续等待。
    在这里插入图片描述
    举例:安全性算法:

    在这里插入图片描述
  3. 解除死锁
    常采用的方法有:
    (1)剥夺资源:从其它进程剥夺足够数量的资源给死锁进程,以解除死锁状态。
    (2)撤消进程:可以直接撤消死锁进程或撤消代价最小的进程,直至有足够的资源可用。

内存管理的方式

  1. 块式管理:把主存分为一大块一大块的,当所需的程序片段不在主存时就分配一块主存空间,就算所需的程序片段只有几个字节也只能把这一块分配给它。这样会造成很大的浪费,平均浪费了50%的内存空间,但是易于管理。
  2. 页式管理:把主存分为一页一页的,每一页的空间要比一块一块的空间小很多,这种方法的空间利用率要比块式管理高很多
  3. 段式管理:把主存分为一段一段的,每一段的空间又要比一页一页的空间小很多。缺点在于一个程序片段可能会被分为几十段,这样很多时间就会被浪费在计算每一段的物理地址上。
  4. 段页式管理:结合了段式管理和页式管理的优点。把主存先分成若干段,每个段又分成若干页。段页式管理每取一次数据,要访问3次内存。
    分页和分段的区别:
    (1)页是信息的物理单位,段是信息的逻辑单位。
    (2)页的大小固定且由系统确定,段的长度却不固定。

虚拟内存

什么是虚拟内存?
虚拟内存简称虚存,是一种内存管理技术,它会使程序认为自己拥有一块很大且连续的内存,然而,这个程序在内存中不是连续的,并且有些还会在磁盘上,在需要时进行数据交换。
如何实现的“不连续代替连续”?
虚拟内存技术的核心就是利用了局部性原理,把进程中常用的数据加载到内存中。不常用的部分以虚拟页的形式存放在磁盘中,使用时再从磁盘中调度到内存中。
虚拟内存

作业调度算法

  1. 先来先服务(FCFS)
    算法简单,但效率低;对长作业比较有利,但对短作业不利;有利于CPU繁忙型作业,而不利于I/O繁忙型作业。

  2. 短作业优先(SJF)平均等待时间、平均周转时间最少
    该算法对长作业不利。更严重的是,可能会导致长作业陷入“饥饿”。
    该算法完全未考虑作业的紧迫程度,因而不能保证紧迫性作业会被及时处理。

  3. 时间片轮转
    时间片轮转调度算法主要适用于分时系统。在这种算法中,系统将所有就绪进程按到达时间的先后次序排成一个队列,FIFO,但每个只能运行一个时间片,如100ms。时间到了后会被剥夺然后放到队尾。
    在时间片轮转调度算法中,时间片的大小对系统性能的影响很大
    时间片太大 -->退化成了先来先服务。
    时间片太小 --> 进程间切换太频繁,开销增大,反而影响效率。
    因此时间片的大小应选择适当。

  4. 优先级调度
    分为非剥夺式和剥夺式,区别在于:
    一个进程正在运行的同时有优先级更高的任务进入,
    非剥夺式 -----> 继续运行直到自己主动退出,才分配给高优先级。(任务管理系统的引擎执行使用的就是这个算法)
    剥夺式 ------> 立即暂停正在运行的,将处理机分配给更重要或紧迫的进程。

  5. 多级反馈队列调度 (剥夺式优先级+时间片轮转)
    (任务管理系统的任务池也使用了多级优先级队列)
    实现细节:
    (1)每个队列给的时间片大小不同,1<2<3<…
    (2)先执行第1级队列,如果时间片执行不完,则退出放到第2级队列,之后同理。
    (3)第1级队列为空时,才执行第2级,之后同理
    (4)当有更高级的进程进入,立即剥夺当前进程,丢回原队列。
    在这里插入图片描述

计算机网络

TCP/IP五层模型

  1. 应用层(HTTP):为用户提供应用接口。
  2. 传输层(TCP/UDP):提供端对端的接口
  3. 网络层(IP):选择合适的路由
  4. 数据链路层:传输帧。
  5. 物理层:传输二进制。

HTTP(基于TCP、C/S模型)

TCP协议使用三次握手建立连接四次挥手关闭连接

TCP三次握手 及状态变化

个人理解:seq为序列号,可以理解为A和B自己的签名,而ack为确认。
发送时,对方的信息使用ack,自己的信息使用seq。
第一次握手:建立连接时,客户端A发送SYN包[SYN=1,ACK=0,seq=x](随机选择一个初始序号seq=x)到服务器B,等待服务器B确认,并进入SYN_SENT状态
第二次握手:服务器B收到SYN包,必须确认客户A的SYN,同时自己也发送一个SYN包,即SYN+ACK包[SYN=1,ACK=1,seq=y,ack=x+1],并进入SYN_RECV状态
第三次握手:客户端A收到服务器B的ACK包,向服务器B发送确认包ACK[ACK=1,seq=x+1,ack=y+1],A和B进入ESTABLISHED状态
在这里插入图片描述
为什么需要三次握手而不是两次呢?
主要是为了防止已经失效的请求突然又到达了B这一现象。
假设A的请求已经失效,B向A发送确认报文建立连接,但是A并不会理会B,导致B一直在等待,造成资源的浪费。

四次挥手

ack和seq与上同理。
(1)A发现自己没有数据需要传输,此时向B发送[FIN = 1,seq=u](u等于前面已经发送过的数据的最后一个字节加一)数据。
(2)B会向A发送ACK确认数据[ACK=1,seq=v,ack=u+1 ],此时A --> B方的连接已经关闭了
(3)当B的应用进程发现自己也没有数据需要传送,此时向A发送[FIN=1,ACK=1,seq=w,ack=u+1]数据
(4)A收到后,向B发送ACK确认数据[ACK =1,seq=u+1,ack=w+1],进行等待状态,等待2MSL(Maximum Segment Lifetime,报文最大生存时间)之后正常关闭连接
在这里插入图片描述

TCP四次挥手客户端关闭链接为什么要等待2倍MSL?

如果Client直接CLOSED了,假设此时Server没有收到Client最后回复的ACK。那么Server就会在超时之后继续发送FIN,此时由于Client已经CLOSED了,因此Server找不到彼此的连接,Server就无法按照正常的步骤进入CLOSED状态误。

拥塞控制

拥塞控制就是防止过多的数据注入到网络中。

  1. 慢开始和拥塞避免
    维持一个拥塞窗口cwnd和慢开始门限ssthresh
    -当cwnd<ssthresh时,使用慢开始算法。
    -当cwnd>ssthresh时,改用拥塞避免算法。
    -当cwnd=ssthresh时,慢开始与拥塞避免算法任意。
    -当出现阻塞,慢开始门限设置为出现拥塞时的发送窗口大小的一半,然后把拥塞窗口设置为1,执行慢开始算法。
    在这里插入图片描述
  2. 快重传和快恢复
    快重传:
    在这里插入图片描述
    快恢复:
    当发送方连续收到三个重复确认时,把ssthresh门限减半,然后将cwnd设置为ssthresh的大小,执行拥塞避免算法。如下图:
    在这里插入图片描述

TCP和UDP区别

  1. 基于连接vs无连接:TCP是面向连接的协议,而UDP是无连接的协议。
  2. 可靠性vs不可靠: TCP可靠,而UDP是不可靠的,数据报在运输途中可能会丢失。
  3. 速度:TCP速度比较慢,而UDP速度比较快。
  4. 对系统资源的要求:TCP较多,UDP少
  5. 流模式(TCP)与数据报模式(UDP)

使用场景:对实时性要求高场合下使用UDP;比如视频。
对可靠性要求高的情况下使用TCP。

TCP为什么可靠

因为其使用三次握手建立连接四次挥手关闭连接;并且有阻塞控制功能。

HTTP返回码

200:请求被正常处理
3xx:表示客户端被重定向到其他资源
4xx:客户端由错误
5xx:服务器端有错误
其中301是永久重定向(抓取新的内容的同时也将旧的网址替换为了重定向之后的网址),
302是临时重定向(抓取新的内容,但会保留旧的地址)

HTTP 长连接、短连接(实际就是TCP的长连接、短链接)

在HTTP/1.0中默认使用短连接。也就是说,客户端和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接。
而从HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头加入这行代码:Connection:keep-alive
Keep-Alive不会永久保持连接,它有一个保持时间,由服务器端设定。

HTTP请求和响应步骤

在这里插入图片描述

HTTPS工作原理

其实就是非对称的签名验签+对称的加解密的过程。
在这里插入图片描述

HTTP请求和响应的结构

HTTP请求报文:
一个HTTP请求报文由请求行(request line)、请求头部(header)、空行和请求数据4个部分组成
在这里插入图片描述

  1. 请求行:请求方法字段、URL字段和HTTP协议版本字段3个字段组成,它们用空格分隔。
    例如,GET /index.html HTTP/1.1。
  2. 请求头部:由key:value对组成,每行一对。
    例如User-Agent:产生请求的浏览器类型。
    Accept:客户端可识别的内容类型列表。
    Host:请求的主机名。
  3. 空行、请求数据(略)

HTTP响应报文:
HTTP响应也由三个部分组成,分别是:状态行、头、空行和正文。
可以看出,与请求报文的区别在于第一行变成了状态行。
状态行格式:HTTP协议的版本,响应状态代码,描述
例如:HTTP/1.1 200 OK

HTTP请求方式:

主要就是get、post和put

  • get:获取资源
  • post、put:提交数据
  • DELETE:删除
  • TRACE:回显请求

get和post的区别

(HTTP规定,当执行GET请求的时候,要给汽车贴上GET的标签(设置method为GET),而且要求把传送的数据放在车顶上(url中)以方便记录。如果是POST请求,就要在车上贴上POST的标签,并把货物放在车厢里。实际上,HTTP只是个行为准则。也就是说,由于TCP才是GET和POST怎么实现的基本,其实get往报文中传输也可以,post往url中传输也可以)

  1. 传送方式:get通过地址栏传输,post通过报文传输。
  2. 传送长度:get参数有长度限制(受限于url长度),而post无限制
  3. 对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
    而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。

put 和 post的区别(了解)

幂等:幂等是数学的一个用语,对于单个输入或者无输入的运算方法,如果每次都是同样的结果,则称其是幂等的。
put是幂等的,例如一个账户对应一个账户二维码,因此适合使用put。
post是非幂等,支付二维码每次打开都应该不同,因此适合使用post。

浏览器中输入URL到页面返回的全过程/Http协议实现的原理机制(重要)

第一步、浏览器中输入域名www.baidu.com
第二步、域名解析:把域名解析成对应的IP
第三步、浏览器与目标服务器建立TCP连接
第四步、向目标服务器发送请求
第五步、服务器给出响应(有可能会重定向,此时浏览器会使用重定向的域名从头开始)
第六步、TCP释放链接
第七步、浏览器显示页面
其中域名解析涉及到缓存:会试先访问浏览器的DNS缓存,没有的话再去访问操作系统的DNS缓存(一张域名与IP地址的对应表),再没有访问host文件,再没有才去本地域名服务器查询。

cookie和session的区别(了解)

cookie 和session 的区别:
1、cookie数据存放在客户端的浏览器上,session数据放在服务器上。
2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
考虑到安全应当使用session。
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
考虑到减轻服务器性能方面,应当使用COOKIE。

所以个人建议:
将登陆信息等重要信息存放为SESSION
其他信息如果需要保留,可以放在COOKIE中

数据库

Mysql两种常用存储引擎myisam和innodb

  1. 区别:
    myisam 不支持事物,只支持表级锁,不支持外键,索引是索引,数据是数据。
    innodb 支持事务和行级锁,支持外键,索引即数据。
    如果系统读多写少,对原子性要求低 --> myisam。
    如果系统读少写多的时候,尤其是并发写入高的时候 --> InnoDB就是首选了。
  2. 索引不同(具体见后文):
    myisam(非聚簇):叶子节点存的是数据地址。
    innodb(聚簇):叶子节点存的是数据本身。

数据库如何应对大规模写入和读取?

  1. 读写分离
    读写分离就是在主服务器上修改数据,数据会同步到从服务器,从服务器只能读取数据,不能写入。
    在这里插入图片描述
  2. 分库分表
    分表(解决单表数据量过大带来的查询效率下降):
    水平切分:不修改数据库表结构,通过对表中数据的拆分而达到分片的目的,一般水平拆分在查询数据库的时候可能会用到 union 操作(多个结果并)。
    可以根据hash或者日期进行进行分表。
    垂直切分:修改表结构,按照访问的差异将某些列拆分出去,一般查询数据的时候可能会用到 join 操作;把常用的字段放一个表,不常用的放一个表,把字段比较大的比如text的字段拆出来放一个表里面。
    分库(提升并发能力):采用关键字取模的方法
    在这里插入图片描述
  3. 使用nosql

数据库事务及其隔离级别

  1. 特性:
    (1)原子性(atomicity) :表示一个事务内的所有操作都是一个整体,要么全部成功,要么全部失败。
    (2)一致性(consistency) :表示一个事务内有一个操作失败了,所有更改过的数据都必须回滚到修改前的状态。
    (3)隔离性(isoation) :多个用户并发访问数据库时,多个并发事务之间的操作不会干扰。
    (4)持久性(durability) :事务完成之后,它对于系统的影响是永久性的。
  2. 隔离问题:
    脏读:一个事务读到另一个事务没有提交的数据
    不可重复读:在一个事务里面读取了两次某个数据,读出来的数据不一致(update)
    虚读(幻读):两次读取,发现多了/少了一些数据(insert,delete)
  3. 隔离级别:
    read uncommitted:读未提交。存在3个问题
    read committed:读已提交。解决脏读,存在2个问题
    repeatable read:可重复读。解决:脏读、不可重复读,存在1个问题。
    serializable :串行化。都解决,单事务

mysql的存储原理:(mySql 索引)

mysql索引使用了b+树这一数据结构。
InnoDB使用的是聚簇索引,行数据和主键B+树存储在一起,辅助键B+树只存储辅助键和主键。若使用"where id = 14"这样的条件查找主键,则在主索引B+树中获取id对应的数据。若对Name列进行条件搜索,则需要两个步骤:从辅助键b+树中获取name对应的id。第二步在主索引B+树中获取id对应的数据。
MyISM使用的是非聚簇索引,非聚簇索引的两棵B+树没什么不同,这两颗B+树的叶子节点都使用一个地址指向真正的表数据,通过辅助键检索无需访问主键的索引树。
在这里插入图片描述

索引的最左匹配原则(即从左往右匹配)

在联合索引中,从左往右进行匹配。
例如建立(a,b,c,d)顺序的索引,那么匹配顺序是a,b,c,d
KEY test_col1_col2_col3 on test(col1,col2,col3);
联合索引 test_col1_col2_col3 实际建立了(col1)、(col1,col2)、(col,col2,col3)三个索引。
SELECT * FROM test WHERE col1=“1” AND clo2=“2” AND clo4=“4”
上面这个查询语句执行时会依照最左前缀匹配原则,检索时会使用索引(col1,col2)进行数据匹配。
注:下面两条语句效果实际上是一样的,因为第二条语句会被mysql优化器调整第一条

SELECT * FROM test WHERE col1=“1” AND clo2=“2”
SELECT * FROM test WHERE col2=“2” AND clo1=“1”

介绍b+树

首先介绍B树,B树事实上是一种平衡的多叉查找树。
在这里插入图片描述
而B+树相对于b树的差别在于:

  • 非叶结点仅具有索引作用。
  • 树的所有叶结点构成一个有序链表。
    在这里插入图片描述

B树(包括B+)和二叉查找树的性能对比?

B树包括B+树的设计思想都是尽可能的降低树的高度,以此降低磁盘IO的次数,因为一个索引节点就表示一个磁盘页,页的换入换出次数越多,表示磁盘IO次数越多,越低效。

redis

https://blog.csdn.net/qq_34337272/article/details/80012284

猜你喜欢

转载自blog.csdn.net/bintoYu/article/details/86763824