cbirdcn.github.io

http://www.zhzq.site

View the Project on GitHub

服务端重点-详情

计算机理论与实践

操作系统与网络

OS面试 OS面试 OS面试 网络面试 网络面试 网络面试 TCP/IP协议

网络协议
介绍一下OSI七层模型和TCP五层模型,及每层涉及协议

OSI七层模型从上到下依次为:

  1. 应用层:为应用程序提供网络服务;如HTTP,FTP,POP3,TELNET,DNS以及DHCP,BOOTP,SSL
  2. 表示层:数据格式转换、数据压缩和数据加密;
  3. 会话层:建立、断开和维护通信链接;
  4. 传输层:为上层协议提供端到端的可靠传输;TCP,UDP
  5. 网络层:寻址和路由;IP协议包含众多,如多播IGMP,地址解析ARP,认证AH,控制消息(网络、路由检测)ICMP
  6. 数据链路层:定义通过通信媒介互连的设备之间传输的规范;IEEE802.X包含:点对点隧道PPTP,VPN第二层通道L2TP,以太网上点对点PPPoE等
  7. 物理层:利用物理传输介质为数据链路层提供物理连接。

TCP五层模型相比OSI七层模型,将OSI的应用层、表示层和会话层合为一层:应用层,其他不变。

image

TCP/IP协议简介

是利用 IP 进行通信时所必须用到的协议群的统称。IP 或 ICMP、TCP 或 UDP、TELNET 或 FTP、以及 HTTP 等都属于 TCP/IP 协议。

数据包:

每个分层中,都会对所发送的数据附加一个首部。
在这个首部中包含了该层必要的信息,如发送的目标地址以及协议相关信息。
通常,为协议提供的信息为包首部,所要发送的内容为数据。
在下一层的角度看,从上一层收到的包全部都被认为是本层的数据。
首部的结构由协议的具体规范详细定义。
在数据包的首部,明确标明了协议应该如何读取数据。

image

数据处理流程:

如图

image

其中:

IP 模块的处理:
    IP 模块接收到 数据后,从包首部中判断此 IP 地址是否与自己的 IP 地址匹配
    如果匹配则根据首部的协议类型将数据发送给对应的模块,如 TCP、UDP。
    对于有路由器的情况,接收端地址往往不是自己的地址。
    此时,需要借助路由控制表,在调查应该送往的主机或路由器之后再进行转发数据。
TCP 模块的处理:
    首先会计算一下校验和,判断数据是否被破坏。
    然后检查是否在按照序号接收数据。
    检查端口号,确定具体的应用程序。
    数据被完整地接收以后,会传给由端口号识别的应用程序。
传输层中的 TCP 和 UDP

传输层协议有两个,分别是 TCP 和 UDP

简介与比较:

TCP是面向连接的、可靠的流协议。
流就是指不间断的数据结构。
当应用程序采用TCP发送消息时,虽然可以保证发送的顺序,但还是犹如没有任何间隔的数据流发送给接收端。
TCP为提供可靠性传输,实行“顺序控制”或“重发控制”机制。
此外还具备“流控制(流量控制)”、“拥塞控制”、提高网络利用率等众多功能。
  
UDP是不具有可靠性的数据报协议。
细微的处理它会交给上层的应用去完成。
在UDP的情况下,虽然可以确保发送消息的大小,却不能保证消息一定会到达。
因此,应用有时会根据自己的需要进行重发处理。
  
TCP和UDP的优缺点无法简单地、绝对地去做比较:
    TCP用于在传输层有必要实现可靠传输的情况;
    而在一方面,UDP主要用于那些对高速传输和实时性有较高要求的通信或广播通信。
    TCP和UDP应该根据应用的目的按需使用。

根据端口号识别应用:

数据链路和 IP 中的地址,分别指的是 MAC 地址和 IP 地址。
前者用来识别同一链路中不同的计算机,后者用来识别 TCP/IP 网络中互连的主机和路由器。
在传输层也有这种类似于地址的概念,那就是端口号。
端口号用来识别同一台计算机中进行通信的不同应用程序。
常用端口号:http80,ftp21,ssh22
知名端口号:分布在0~1023之间
其他端口号:1024~49151之间,可用于任何通信用途。

识别一个通信:

image

UDP详细:

UDP 不提供复杂的控制机制,利用IP提供面向无连接的通信服务。
并且它是将应用程序发来的数据在收到的那一刻,立即按照原样发送到网络上的一种机制。
即使是出现网络拥堵的情况,UDP也无法进行流量控制等避免网络拥塞行为。
此外,传输途中出现丢包,UDP 也不负责重发。
甚至当包的到达顺序出现乱序时也没有纠正的功能。

UDP 常用于以下几个方面:
    1.包总量较少的通信(DNS、SNMP等);
    2.视频、音频等多媒体通信(即时通信);
    3.限定于LAN等特定网络中的应用通信;
    4.广播通信(广播、多播)。

TCP详细:

TCP与UDP的区别相当大。
它充分地实现了数据传输时各种控制功能,可以进行丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。
而这些在 UDP 中都没有。
此外,TCP 作为一种面向有连接的协议,只有在确认通信对端存在时才会发送数据,从而可以控制通信流量的浪费。
根据 TCP 的这些机制,在IP这种无连接的网络上也能够实现高可靠性的通信( 主要通过检验和、序列号、确认应答、重发控制、连接管理以及窗口控制等机制实现)。

TCP三次握手:

TCP 提供面向有连接的通信传输。
面向有连接是指在数据通信开始之前先做好两端之间的准备工作。
所谓三次握手是指建立一个TCP连接时需要客户端和服务器端总共发送三个包以确认连接的建立。
在socket编程中,这一过程由客户端执行connect来触发。

image

第一次握手:客户端将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给服务器端,客户端进入SYN_SENT状态,等待服务器端确认。
第二次握手:服务器端收到数据包后由标志位SYN=1知道客户端请求建立连接,服务器端将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给客户端以确认连接请求,服务器端进入SYN_RCVD状态。
第三次握手:客户端收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给服务器端,服务器端检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,客户端和服务器端进入ESTABLISHED状态,完成三次握手,随后客户端与服务器端之间可以开始传输数据了。

TCP四次握手:

四次挥手即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。
在socket编程中,这一过程由客户端或服务端任一方执行close来触发。
由于TCP连接是全双工的,因此,每个方向都必须要单独进行关闭。
这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。
首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。

image

中断连接端可以是客户端,也可以是服务器端。
第一次挥手:客户端发送一个FIN=M,用来关闭客户端到服务器端的数据传送,客户端进入FIN_WAIT_1状态。意思是说"我客户端没有数据要发给你了",但是如果你服务器端还有数据没有发送完成,则不必急着关闭连接,可以继续发送数据。
第二次挥手:服务器端收到FIN后,先发送ack=M+1,告诉客户端,你的请求我收到了,但是我还没准备好,请继续你等我的消息。这个时候客户端就进入FIN_WAIT_2状态,继续等待服务器端的FIN报文。
第三次挥手:当服务器端确定数据已发送完成,则向客户端发送FIN=N报文,告诉客户端,好了,我这边数据发完了,准备好关闭连接了。服务器端进入LAST_ACK状态。
第四次挥手:客户端收到FIN=N报文后,就知道可以关闭连接了,但是他还是不相信网络,怕服务器端不知道要关闭,所以发送ack=N+1后进入TIME_WAIT状态,如果Server端没有收到ACK则可以重传。服务器端收到ACK后,就知道可以断开连接了。客户端等待了2MSL后依然没有收到回复,则证明服务器端已正常关闭,那好,我客户端也可以关闭连接了。最终完成了四次握手。

TCP 有哪些状态、time-wait的作用?link

通过序列号与确认应答提高可靠性:

重发超时的确定:

利用窗口控制提高速度:

image

滑动窗口控制:

image

窗口控制中的重发控制:

在使用窗口控制中, 出现丢包一般分为两种情况:

image

TCP粘包是什么?怎么解决这个问题? link

建立TCP服务器的各个系统调用过程是怎样的? link

todo

TCP 协议如何保证可靠传输?

RTO,RTT和超时重传(自动重传ARQ)?

网络层中的IP协议

网络层的主要作用是“实现终端节点之间的通信”。这种终端节点之间的通信也叫“点对点通信”。

网络的下一层——数据链路层的主要作用是在互连同一种数据链路的节点之间进行包传递。而一旦跨越多种数据链路,就需要借助网络层。网络层可以跨越不同的数据链路,即使是在不同的数据链路上也能实现两端节点之间的数据包传输。

IP 大致分为三大作用模块,它们是 IP 寻址、路由(最终节点为止的转发)以及 IP 分包与组包。

IP地址:

路由控制:

IP 协议相关:

HTTP与HTTPS

简介:

HTTP是一个基于TCP/IP通信协议来传递数据的协议。HTTP协议工作于客户端-服务端架构之上,实现可靠性的传输文字、图片、音频、视频等超文本数据的规范,格式简称为“超文本传输协议”。Http协议属于应用层,用户访问的第一层就是http。

特点:

特点:

Http和Https的区别?

HTTPS工作原理?

加密算法?

对称加密,如 AES
基本原理:将明文分成 N 个组,然后使用密钥对各个组进行加密,形成各自的密文,最后把所有的分组密文进行合并,形成最终的密文。
优点:算法公开、计算量小、加密速度快、加密效率高
缺点:双方都使用同样密钥,安全性得不到保证

非对称加密,如 RSA
基本原理:同时生成两把密钥:私钥和公钥,私钥隐秘保存,公钥可以下发给信任客户端
私钥加密,持有私钥或公钥才可以解密
公钥加密,持有私钥才可解密
优点:安全,难以破解
缺点:算法比较耗时

不可逆加密,如 MD5,SHA
基本原理:加密过程中不需要使用密钥,输入明文后由系统直接经过加密算法处理成密文。
这种加密后的数据是无法被解密的,无法根据密文推算出明文。

一次完整的HTTP请求所经历几个步骤?

HTTP协议采用请求/响应模型。客户端向服务器发送一个请求报文,请求报文包含请求方法、URL、协议版本、请求头部和请求数据。服务器以一个状态行作为响应,响应内容包括协议版本、成功或者错误的代码、服务器信息、响应头部和响应数据。

Web浏览器与Web服务器之间将完成下列7个步骤:

HTTP请求和响应报文?

todo

输入网址到获取页面的过程?

http版本的对比?

HTTP Keep-Alive是什么?如何工作?link

http keep-alive与tcp keep-alive:

keep-alive与TIME_WAIT:

image

常用HTTP状态码是怎么分类的,有哪些常见的状态码?

image

常用状态码:

200: 请求被正常处理
204: 请求被受理但没有资源可以返回
301: 永久性重定向
302: 临时重定向
304: 已缓存
400: 请求报文语法有误,服务器无法识别
403: 请求的对应资源禁止被访问
404: 服务器无法找到对应资源
500: 服务器内部错误
503: 服务器正忙

todo,认证等

HTTP协议中的请求方式(动词,Method)?

RESTful API中http method的含义?

todo

GET方法与POST方法的区别?

Session 与 Cookie 的对比?

HTTP协议本身是无状态的,无法判断用户身份。所以需要cookie或者session。

cookie:

session:

比较:

http强缓存与协商缓存? link

浏览器第一次向一个web服务器发起http请求后,服务器会返回请求的资源,并且在响应头中添加一些有关缓存的字段如:Cache-Control、Expires、Last-Modified、ETag、Date等等。之后浏览器再向该服务器请求该资源就可以视情况使用强缓存和协商缓存。

强缓存-几个Cache-Control的常用指令:

若缓存未过期,返回状态码为200,则直接从本地读取缓存。如果缓存过期,则进入协商缓存或服务器返回新资源过程

协商缓存:

当浏览器发现缓存过期后,缓存并不一定不能使用了,因为服务器端的资源可能仍然没有改变,所以需要与服务器协商,让服务器判断本地缓存是否还能使用。

浏览器会判断缓存中是否有ETag或Last-Modified字段,如果没有,则发起一个http请求,服务器根据请求返回资源;如果有这两个字段,则在请求头中添加If-None-Match字段(有ETag字段的话添加)、If-Modified-Since字段(有Last-Modified字段的话添加)。

服务器判断缓存是否可用。如果与服务器内容不一致,则视情况返回其他状态码,并返回所请求资源。

用户行为对浏览器缓存的影响:

image

Http能不能一次连接多次请求,不等后端返回? link

首先,分析浏览器在与服务器建立了一个 TCP 连接后是否会在一个 HTTP 请求完成后断开?什么情况下会断开?

HTTP/1.1 存在一个问题,单个 TCP 连接在同一时刻只能处理一个请求,意思是说:两个请求的生命周期不能重叠,任意两个 HTTP 请求从开始到结束的时间在同一个 TCP 连接里不能重叠。 虽然 HTTP/1.1 规范中规定了 Pipelining 来试图解决这个问题,但是这个功能在浏览器中默认是关闭的。

实践中会出现许多问题,所以默认不开启Pipelining:

HTTP2 提供了 Multiplexing 多路传输特性,可以在一个 TCP 连接中同时完成多个 HTTP 请求。

image

绿色是发起请求到请求返回的等待时间,蓝色是响应的下载时间,可以看到都是在同一个 Connection,并行完成的

那么在 HTTP/1.1 时代,浏览器是如何提高页面加载效率的呢?

浏览器对同一 Host 建立 TCP 连接到数量有没有限制?

WebSocket与TCP,HTTP的关系?

在JavaScript中创建了WebSocket后,会有一个HTTP请求发送到服务器以发起连接。取得服务器响应后,建立的连接使用HTTP升级,从HTTP协议交换为WebSocket协议。即,使用标准的HTTP服务器无法实现WebSocket,只有支持这种协议的专门服务器才能正常工作。 WebSocket使用了自定义的协议,未加密的连接不再是http://,而是ws://,默认端口为80,加密的连接也不是https://,而是wss://,默认端口为443。 WebSocket模式客户端与服务器请求响应模式如图:

![image](https://upload-images.jianshu.io/upload_images/5088376-ebc5399ed29120a8.png?imageMogr2/auto-orient/strip imageView2/2/w/542/format/webp)

WebSocket是类似Socket的TCP长连接通讯模式。一旦WebSocket连接建立后,后续数据都以帧序列的形式传输。在客户端断开WebSocket连接或Server端中断连接前,不需要客户端和服务端重新发起连接请求。在海量并发及客户端与服务器交互负载流量大的情况下,极大的节省了网络带宽资源的消耗,有明显的性能优势,且客户端发送和接受消息是在同一个持久连接上发起,实时性优势明显。

WebSocket API?

todo

时延(delay或latency)是指数据(一个报文或分组,甚至比特)从网络(或链路)的一端传送到另一端所需的时间。有时也称为延迟或迟延。

DNS用来将主机名和域名转换为IP地址的工作。

域名系统作为一个层次结构和分布式数据库,包含各种类型的数据,包括主机名和域名。DNS数据库中的名称形成一个分层树状结构称为域命名空间。

查询过程:

DNS为什么不采用单点的集中式的设计方式,而是使用分布式集群的工作方式?

因特网有着数量巨大并且在持续增长的主机,分布式集群解决以下问题:

建立一个 socket 连接要经过哪些步骤? link

todo

操作系统

link link link

进程在系统上的运行分为2个级别

用户态切换到内核态的三种方式:

系统调用:用户态进程主动要求切换到内核态的一种方式。用户态进程通过系统调用,申请使用操作系统提供的服务程序,以完成工作。

系统调用(system call)提供操作系统服务接口。这些调用通常以 C 或 C++ 编写。即使简单程序(如写文件)也可能大量使用操作系统。通常,系统每秒执行成千上万的系统调用。不过,应用程序开发人员根据应用编程接口(Application Programming Interface,API)来设计程序。API 为方便应用程序员规定了一组函数,包括每个函数的输入参数和返回值。

有三组常见 API 可为应用程序员所用:适用于 Windows 系统的 Windows API、适用于 POSIX 系统的 POSIX API(这包括几乎所有版本的 UNIX、Linux 和 Mac OS X)以及适用于 Java 虚拟机的 Java API。程序员通过操作系统提供的函数库来调用 API。对运行于 UNIX 和 Linux 的用 C 语言编写的程序,该库名为 libc。

对大多数的程序设计语言,运行时支持系统(由编译器直接提供的函数库)提供了系统调用接口(system-call interface),以链接到操作系统的系统调用。系统调用接口截取 API 函数的调用,并调用操作系统中的所需系统调用。通常,每个系统调用都有一个相关数字,而系统调用接口会根据这些数字来建立一个索引列表。系统调用接口就可调用操作系统内核中的所需系统调用,并返回系统调用状态与任何返回值。调用者无需知道如何实现系统调用,而只需遵循 API,并知道在调用系统调用后操作系统做了什么。因此,通过 API,操作系统接口的大多数细节可隐藏起来,且可由运行时库来管理。

在用户应用程序调用了系统调用 open() 后,操作系统是如何处理的。如图: image

向操作系统传递参数有三种常用方法。 最简单的是通过寄存器来传递参数。不过,有时参数数量会比寄存器多。这时,这些参数通常存在内存的块或表中,而块或表的地址通过寄存器来传递(图 3)。Linux就是这样。

image

参数也可通过程序放在或压入(pushed)到堆栈(stack),并通过操作系统弹出(popped)。有的系统偏爱块或堆栈方法,因为这些方法并不限制传递参数的数量或长度。

CPU大部分的时间都是停留在”idle task”中。在Linux中,idle task并不是一个独立的线程,但是可以通过top指令查看CPU的idle比例

image

当CPU执行HLT指令后,CPU就会停止指令的执行,并且让CPU处于HALT状态。当CPU处于HALT状态的时候,CPU虽然停止指令执行,并且CPU的部分功能模块将会被关闭(达到降低功耗的目的),但是CPU的LAPIC(Local Advanced Programmable Interrupt Controller)并不会停止工作,即CPU将会继续接收外部中断、异常等外部事件(事实上,CPU HALT状态的退出将由外部事件触发)。当CPU接收到这些外部事件的时候,将会从HALT状态恢复回来,执行中断服务函数,并且当中断服务函数执行完毕后,指令寄存器(CS:EIP)将会指向HLT指令的下一条指令,即CPU继续执行HLT指令之后的程序。

操作系统32位与64位区别

主要体现在支持的内存、处理器、软件、处理数据的能力以及体积的大小等方面。

编译器和解释器之间有什么区别

都表示CPU执行多个任务的方式。

对于单CPU的计算机来说,在CPU中,同一时间是只能干一件事儿的。

为了看起来像是“同时干多件事”操作系统把CPU的时间划分成长短基本相同的时间区间,即”时间片”,通过操作系统的管理,把这些时间片依次轮流地分配给各个应用使用。

这样,给用户的感觉是他在同时的进行听歌和打游戏,实际上,在操作系统中,CPU是在游戏进程和音乐播放器进程之间来回切换执行的。

操作系统时间片的使用是有规则的:某个作业在时间片结束之前,整个任务还没有完成,那么该作业就被暂停下来,放弃CPU,等待下一轮循环再继续做。此时CPU又分配给另一个作业去使用。

由于计算机的处理速度很快,只要时间片的间隔取得适当,那么一个用户作业从用完分配给它的一个时间片到获得下一个CPU时间片,中间有所”停顿”,但用户察觉不出来。

所以,在单CPU的计算机中,我们看起来“同时干多件事”,其实是通过CPU时间片技术,并发完成的。

所以,并发(Concurrent),在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行。

并行(Parallel),当系统有一个以上CPU时,当一个CPU执行一个进程时,另一个CPU可以执行另一个进程,两个进程互不抢占CPU资源,可以同时进行。

进程与线程、协程的区别,进程与线程切换流程

link

概念:

区别:

进程多与线程比较

线程是指进程内的一个执行单元,也是进程内的可调度实体。

线程与进程的区别:

协程多与线程进行比较

总结,进程、线程、协程的关系和区别:

进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度。 线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的)。 协程和线程一样共享堆,不共享栈,协程由程序开发者在协程的代码里显示调度。

线程切换的开销比进程切换的开销小,那么小在什么地方?切换的过程是怎样的?

无论是在多核还是单核系统中,一个CPU看上去都像是在并发的执行多个进程,这是通过处理器在进程间切换来实现的。

在任何一个时刻,单处理器系统都只能执行一个进程的代码。

当操作系统决定要把控制权从当前进程转移到某个新进程时,就会进行上下文切换,即保存当前进程的上下文,恢复新进程的上下文,然后将控制权传递到新进程,新进程就会从上次停止的地方开始

举例:

上下文切换: 内核为每一个进程维持一个上下文。上下文就是内核重新启动一个被抢占的进程所需的状态。包括:

进程切换:

系统中的每个程序都是运行在某个进程的上下文中的。

上下文是由程序正确运行所需的状态组成的,这个状态包括存放在存储器中的程序的代码和数据,他的栈,通用目的寄存器的内容,程序计数器,环境变量以及打开文件描述符的集合。

所以进程切换就是上下文切换。

虚拟内存:

虚拟内存是操作系统为每个进程提供的一种抽象,每个进程都有属于自己的、私有的、地址连续的虚拟内存,当然我们知道最终进程的数据及代码必然要放到物理内存上,那么必须有某种机制能记住虚拟地址空间中的某个数据被放到了哪个物理内存地址上,这就是所谓的地址空间映射,那么操作系统是如何记住这种映射关系的呢,答案就是页表。

每个进程都有自己的虚拟地址空间,进程内的所有线程共享进程的虚拟地址空间。

进程切换和线程切换有什么区别?(线程指的是同一个进程中的线程)需要理解虚拟内存。

进程间通信(Inter-Process Communication,IPC):

每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程A把数据从用户空间拷到内核缓冲区,进程B再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信。

进程间通信方式:

优缺点:

线程间的通信

todo

进程间同步的方式
线程同步的方式

区别:

线程的分类

从线程的运行空间来说,分为用户级线程(user-level thread, ULT)和内核级线程(kernel-level, KLT)

同一进程间的线程究竟共享哪些资源呢,而又各自独享哪些资源呢?

共享的资源:

独享的资源:

什么是临界区?如何解决冲突?

每个进程中访问临界资源的那段程序称为临界区,一次仅允许一个进程使用的资源称为临界资源。

解决冲突的办法:

什么是死锁?死锁产生的条件?

死锁:

在两个或者多个并发进程中,如果每个进程持有某种资源而又等待其它进程释放它或它们现在保持着的资源,在未改变这种状态之前都不能向前推进,称这一组进程产生了死锁。通俗的讲就是两个或多个进程无限期的阻塞、相互等待的一种状态。

死锁产生的四个必要条件:(有一个条件不成立,则不会产生死锁)

如何处理死锁问题:

死锁检测、恢复、预防?

todo

进程调度策略(算法)?

时间片轮转算法的效率和时间片的大小有很大关系:

优先级调度:

为每个进程分配一个优先级,按优先级进行调度。为了防止低优先级的进程永远等不到调度,可以随着时间的推移增加等待进程的优先级。

进程有哪些状态?如何切换?

进程一共有5种状态,分别是创建、就绪、运行(执行)、终止、阻塞。

image

状态转换:

什么是分页?

把内存空间划分为大小相等且固定的块,作为主存的基本单位。因为程序数据存储在不同的页面中,而页面又离散的分布在内存中,因此需要一个页表来记录映射关系,以实现从页号到物理块号的映射。

访问分页系统中内存数据需要两次的内存访问 (一次是从内存中访问页表,从中找到指定的物理块号,加上页内偏移得到实际物理地址;第二次就是根据第一次得到的物理地址访问内存取出数据)。

image

什么是分段?

分页是为了提高内存利用率,而分段是为了满足程序员在编写代码的时候的一些逻辑需求(比如数据共享,数据保护,动态链接等)。

分段内存管理当中,地址是二维的,一维是段号,二维是段内地址;其中每个段的长度是不一样的,而且每个段内部都是从0开始编址的。由于分段管理中,每个段内部是连续内存分配,但是段和段之间是离散分配的,因此也存在一个逻辑地址到物理地址的映射关系,相应的就是段表机制。

image

分页和分段有什区别?
什么是交换空间?

操作系统把物理内存(physical RAM)分成一块一块的小内存,每一块内存被称为页(page)。当内存资源不足时,Linux把某些页的内容转移至硬盘上的一块空间上,以释放内存空间。硬盘上的那块空间叫做交换空间(swap space),而这一过程被称为交换(swapping)。物理内存和交换空间的总容量就是虚拟内存的可用容量。

用途:

页面替换算法是什么,有哪些?

在程序运行过程中,如果要访问的页面不在内存中,就发生缺页中断从而将该页调入内存中。此时如果内存已无空闲空间,系统必须从内存中调出一个页面到磁盘对换区中来腾出空间。

包括以下算法:

什么是虚拟内存?

虚拟内存就是,让物理内存扩充成更大的逻辑内存,从而让程序获得更多的可用内存。虚拟内存使用部分加载的技术,让一个进程或者资源的某些页面加载进内存,从而能够加载更多的进程,甚至能加载比内存大的进程,这样看起来好像内存变大了,这部分内存其实包含了磁盘或者硬盘,这就叫做虚拟内存。

什么是缓冲区溢出?有什么危害?

缓冲区溢出是指当计算机向缓冲区填充数据时超出了缓冲区本身的容量,溢出的数据覆盖在合法数据上。

危害有以下两点:

造成缓冲区溢出的主要原因是程序中没有仔细检查用户输入。

讲一讲IO多路复用?

IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程。

IO多路复用适用如下场合:

硬链接和软链接有什么区别?
中断的处理过程?
中断和轮询有什么区别?

轮询:

中断:

同步与异步的区别:请求发出后,是否需要等待结果,才能继续执行其他操作。

阻塞与非阻塞: 阻塞和非阻塞这两个概念与程序(线程)等待消息通知(无所谓同步或者异步)时的状态有关。也就是说阻塞与非阻塞主要是程序(线程)等待消息通知时的状态角度来说的。

阻塞非阻塞与同步异步的区别:

磁盘调度算法:
堆与栈的区别,在程序中的使用:

程序的内存分配

举例:

#include<iostream>
using namespace std;

int a = 0;//全局初始化区
char *p1;//全局未初始化区

int main()
{
    int b;//栈
    char s[] = "abc";//栈
    char *p2;//栈
    char *p3 = "123456";//p3在栈,“123456”在常量区
    static int c = 0;//全局初始化区
    p1 = (char *)malloc(10);
    p2 = (char *)malloc(20);
    //分配得来的10和20字节在堆区
    strcpy(p1, "123456");
    //“123456”在常量区,编译器可能会将它与p3所指向的“123456”优化成一个地方
}

注意:Go中的堆与栈

Go语言区别于C/C++,虽然变量申请在堆空间上,但是它有自动回收垃圾的功能,所以这些堆地址空间也无需我们手动回收,系统会在需要释放的时刻自动进行垃圾回收。

内存连续分配算法

在UNIX里,除了进程0(即PID=0的交换进程,Swapper Process)以外的所有进程都是由其他进程使用系统调用fork创建的,这里调用fork创建新进程的进程即为父进程,而相对应的为其创建出的进程则为子进程,因而除了进程0以外的进程都只有一个父进程,但一个进程可以有多个子进程。

操作系统内核以进程标识符(Process Identifier,即PID)来识别进程。进程0是系统引导时创建的一个特殊进程,在其调用fork创建出一个子进程(即PID=1的进程1,又称init)后,进程0就转为交换进程(有时也被称为空闲进程),而进程1(init进程)就是系统里其他所有进程的祖先。

僵尸进程与孤儿进程

当一个子进程结束运行(一般是调用exit、运行时发生致命错误或收到终止信号所导致)时,子进程的退出状态(返回值)会回报给操作系统,系统则以SIGCHLD信号将子进程被结束的事件告知父进程,此时子进程的进程控制块(PCB)仍驻留在内存中。一般来说,收到SIGCHLD后,父进程会使用wait系统调用以取得子进程的退出状态,然后内核就可以从内存中释放已结束的子进程的PCB;而如若父进程没有这么做的话,子进程的PCB就会一直驻留在内存中,也即成为僵尸进程。

孤儿进程则是指父进程结束后仍在运行的子进程。在类UNIX系统中,孤儿进程一般会被init进程所“收养”,成为init的子进程。

僵尸进程的危害:

系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程. 此即为僵尸进程的危害应当避免。

僵尸进程中保存着很多对程序员和系统管理员非常重要的信息,首先,这个进程是怎么死亡的?是正常退出呢,还是出现了错误,还是被其它进程强迫退出的?其次,这个进程占用的总系统CPU时间和总用户CPU时间分别是多少?发生页错误的数目和收到信号的数目。这些信息都被存储在僵尸进程中,试想如果没有僵尸进程,进程一退出,所有与之相关的信息都立刻归于无形.

僵尸资源会造成资源浪费,孤儿进程则不会。

linux常用命令与工具
$ ps aux
USER               PID  %CPU %MEM      VSZ    RSS   TT  STAT STARTED      TIME COMMAND
root              1006  12.0  1.0 12861176 166312   ??  S     5:55下午 165:22.95 com.docker.hyperkit
root               435   5.2  0.3  4853560  48696   ??  S     5:54下午  67:08.37 /Applications/Visual Studio Code.app
kill -signal PID

1:SIGHUP,启动被终止的进程
2:SIGINT,相当于输入ctrl+c,中断一个程序的进行
9:SIGKILL,强制中断一个进程的进行
15:SIGTERM,以正常的结束进程方式来终止进程
17:SIGSTOP,相当于输入ctrl+z,暂停一个进程的进行
service cron start # 启动cronjob
service cron stop # 停止cronjob
service cron restart #  重启cronjob
crontab -e # 编辑cronjob任务
第1列分钟1~59
第2列小时1~23(0表示子夜)
第3列日1~31
第4列月1~12
第5列星期0~6(0表示星期天)
第6列要运行的命令
# crontab -l
* * * * * /usr/local/bin/docker exec -u www-data php-fpm /usr/local/bin/php artisan --env=developer schedule:run > /dev/null 2> /Users/gaea/fns/log/test.log
free [参数]
-b 以Byte为单位显示内存使用情况。 
-k 以KB为单位显示内存使用情况。 
-m 以MB为单位显示内存使用情况。
-g 以GB为单位显示内存使用情况。 
-o 不显示缓冲区调节列。 
-s<间隔秒数> 持续观察内存使用状况。 
-t 显示内存总和列。 
-V 显示版本信息。
# free -m
               total        used        free      shared  buff/cache   available
Mem:            7962        2973        2793          42        2195        4777
Swap:           1023           0        1023
top [参数]
-u<用户名> 指定用户名
-p<进程号> 指定进程
...

结果:

top - 06:49:40 up 20:55,  0 users,  load average: 1.40, 1.34, 0.57
Tasks:   3 total,   1 running,   2 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.3 us,  0.6 sy,  0.0 ni, 99.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   7962.1 total,   2815.9 free,   2949.2 used,   2197.0 buff/cache
MiB Swap:   1024.0 total,   1024.0 free,      0.0 used.   4806.1 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                       
    1 root      20   0    4092   3260   2832 S   0.0   0.0   0:00.03 bash                             
    8 root      20   0    2412    580    508 S   0.0   0.0   0:00.04 sh                                             
   16 root      20   0    6928   3144   2628 R   0.0   0.0   0:00.00 top  

分析: link

- 第一行:系统运行状态和平均负载
    - 第一个参数:目前的时间:06:49:40
    - 第二个参数:系统目前运行的时间:20:55
    - 第三个参数:当前有多少人登录了这个系统:1
    - 第四个参数:系统负载(load average),既任务队列的平均长度,三个数值分别代表最近1分钟,5分钟,15分钟的系统平均负载
        - 对于单核CPU来说,0表示没有负荷,1表示满负荷,大于1表示超负荷,理想值是0.7
        - 对于多核CPU来说,用核数按比例放大就好,比如四核CPU,理想值就是4*0.7=2.8
        - 查看CPU核数:`cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c`
- 第二行:进程相关信息
    - 第一个参数:进程总数:4个
    - 第二个参数:正在运行的进程数 : 1个
    - 第三个参数:睡眠的进程数:3个
    - 第四个参数:停止的进程数 : 0个
    - 第五个参数:僵尸进程数 :0个
- 第三行:cpu信息,**按1可以切换显示多核CPU信息**
    - 第一个参数:**us用户空间**占用的cpu百分比:7.7%
    - 第二个参数:**sy内核空间**占用的cpu百分比:9.1%
    - 第三个参数:**ni用户进程空间内改变过优先级的进程**占用CPU百分比:0%
    - 第四个参数:**id 空闲CPU百分比**:82.7%(关注点)
    - 第五个参数:wa等待输入输出的CPU时间百分比:0%
    - 第六个参数:hi CPU服务于硬件中断所耗费的时间总额:0%
    - 第七个参数:si CPU服务软中断所耗费的时间总额:0.5%
    - 第八个参数:st Steal time 虚拟机被hypervisor偷去的CPU时间:0%
- 第四行:内存信息
    - 第一个参数:mem 物理内存总量 : 后缀是total
    - 第二个参数: 空闲内存总量 : 后缀是free
    - 第三个参数 :使用的物理内存总量 : 后缀是used
    - 第四个参数 : 用作内核缓存的内存量 : 后缀是buff/cache
- 第五行:
    - 第一个参数:交换区总量 : 后缀是total
    - 第二个参数:空闲交换区总量 : 后缀是free
    - 第三个参数:使用的交换区总量 : 后缀是used
    - 第四个参数:缓冲的交换区总量 : 后缀是avail mem
- 进程信息
    - PID(process id):进程id
    - USER (user name):进程所有者的用户名
    - PR (priority) :优先级
    - NI (nice value) : 负值表示高优先级,正值表示低优先级
    - VIRT (Virtual Image (kb)) : 进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES
    - RES (Resident size (kb)) : 进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA
    - SHR (Shared Mem size (kb)) : 共享内存大小,单位kb
    - S (Process Status) : 进程状态。D=不可中断的睡眠状态,R=运行,S=睡眠,T=跟踪/停止,Z=僵尸进程
    - %CPU (CPU usage) : 上次更新到现在的CPU时间占用百分比。这里可能超过100%,每一个100%表示占用了一个CPU,比如230%,表示目前这个进程占用了2核CPU
    - %MEM (Memory usage (RES)) :进程使用的物理内存百分比
    - TIME+ (CPU Time, hundredths) : 进程使用的CPU时间总计,单位1/100秒
    - COMMAND (Command name/line) : 命令名/命令行
scp [参数] [原路径] [目标路径]
-r 递归复制整个目录。 
-v 详细方式显示输出。scp和ssh(1)会显示出整个过程的调试信息。这些信息用于调试连接,验证和配置问题。
-i identity_file 从指定文件中读取传输时使用的密钥文件(私钥),此参数直接传递给ssh。 

举例,从本地(MAC)传递文件到远程服务器(前提是本机生成了公钥,并传到了服务器上对应账号文件夹内):

scp -i /Users/local_account_name/.ssh/id_rsa ./tmp.tar.gz remote_account_name@remote_ip:/tmp

例如,连接本机memcached服务:

telnet 127.0.0.1 11211

只能用于程序名的搜索,而且只搜索二进制文件(参数-b)、man说明文件(参数-m)和源代码文件(参数-s)。如果省略参数,则返回所有信息。和find相比,whereis查找的速度非常快,这是因为linux系统会将 系统内的所有文件都记录在一个数据库文件中,当使用whereis和locate时,会从数据库中查找数据,而不是像find命令那样,通过遍历硬盘来查找,效率自然会很高。 但是该数据库文件并不是实时更新,默认情况下时一星期更新一次,因此,我们在用whereis和locate 查找文件时,有时会找到已经被删除的数据,或者刚刚建立文件,却无法查找到,原因就是因为数据库文件没有被更新。

# which go
/usr/local/go/bin/go

该命令常用于分析一行的信息,若当中有我们所需要的信息,就将该行显示出来,该命令通常与管道命令一起使用,用于对一些命令的输出进行筛选加工等等,比如可以加在ps, tail, cat后面

grep [-acinv] [--color=auto] '查找字符串' filename

参数:
  -a或--text   不要忽略二进制的数据。
  -A<显示列数>或--after-context=<显示列数>  显示该列和之后的内容。
  -c或--count   只打印匹配的行数,不显示匹配的内容。
  -C<显示列数>或--context=<显示列数>或-<显示列数>  显示该列和前后N行的内容。
  -i或--ignore-case   忽略字符大小写的差别。
  -l或--file-with-matches   列出文件内容符合指定的范本样式的文件名称。
  -n或--line-number  在匹配的行前面打印行号。
  -v或--revert-match   反检索,只显示不匹配的行。
ln [参数][源文件或目录][目标文件或目录]
参数:
-s 软链接(符号链接)
$sed [options] 'command' files
 options可以使用下面这几个值:
    -e:可以指定多个command
    -n:与p(print)命令合用时,表示只显示被选中的行,而不是显示所有的行,然后被选中的行会显示两次。
    -i:将sed的操作结果更新到文件中,因为默认的是不会操作文件本身的。
 command:行定位(正则)+ sed命令,首先会通过正则行定位,选中要进行操作的行,然后执行sed命令

举例:

[root@localhost test]# #打印第5行
[root@localhost test]# sed -n "5 p" data.txt

[root@localhost test]# 打印匹配"China"的记录,/pattern/使用正则表达式,注意要包含在/..../之间
[root@localhost test]# sed -n "/china/ p" data.txt

[root@localhost test]# 打印第3~6行
[root@localhost test]# cat -n data.txt | sed -n "3,6 p"

[root@localhost test]# #打印“Jane”的行,到“贝爷”之间的行
[root@localhost test]# sed -n "/Jane/, /贝爷/ p" data.txt
...

语法

awk [选项参数] 'script' var=value file(s)
或
awk [选项参数] -f scriptfile var=value file(s)

举例:

awk '{[pattern] action}' {filenames}   # 行匹配语句 awk '' 只能用单引号
# 每行按空格或TAB分割,输出文本中的1、4项
$ awk '{print $1,$4}' log.txt

awk -F  #-F相当于内置变量FS, 指定分割字符
# 使用","分割
$ awk -F, '{print $1,$2}'   log.txt
# 使用多个分隔符.先使用空格分割,然后对分割结果再使用","分割
$ awk -F '[ ,]'  '{print $1,$2,$5}'   log.txt

过滤与运算法
# 过滤第一列等于2的行
$ awk '$1==2 {print $1,$3}' log.txt
# 过滤第一列大于2并且第二列等于'Are'的行
$ awk '$1>2 && $2=="Are" {print $1,$2,$3}' log.txt

...

Shell 脚本(shell script),是一种为 shell 编写的脚本程序。shell script是一种解释型语言,必须由解释器来执行这些脚本,执行时,解释器将脚本一行一行地转换为代码。 这个解释器就是Shell,它是一个用 C 语言编写的程序。 shell script,通常使用.sh作为扩展名。

# 列出docker容器ID,获取从第2行开始的containerId,再执行 docker start containerId
$ cat docker_start_all.sh 
#!/bin/sh

docker start $(docker ps -a | awk '{ print $1}' | tail -n +2)

C10K问题:

随着互联网的普及,应用的用户群体几何倍增长,此时服务器性能问题就出现。最初的服务器是基于进程/线程模型。新到来一个TCP连接,就需要分配一个进程。假如有C10K,就需要创建1W个进程,可想而知单机是无法承受的。那么如何突破单机性能是高性能网络编程必须要面对的问题,进而这些局限和问题就统称为C10K问题。

本质:

C10K问题本质上是操作系统的问题。对于Web 1.0/2.0时代的操作系统,传统的同步阻塞I/O模型处理方式都是requests per second。当创建的进程或线程多了,数据拷贝频繁(缓存I/O、内核将数据拷贝到用户进程空间、阻塞,进程/线程上下文切换消耗大, 导致操作系统崩溃,这就是C10K问题的本质。

可见, 解决C10K问题的关键就是尽可能减少这些CPU资源消耗。

服务器安全

跨站点脚本攻击,指攻击者通过篡改网页,嵌入恶意脚本程序,在用户浏览网页时,控制用户浏览器进行恶意操作的一种攻击方式。

如何防范XSS攻击: 防 XSS 的核心是必须对输入的数据做过滤处理。

CSRF攻击

跨站点请求伪造,指攻击者通过跨站请求,以合法的用户的身份进行非法操作。攻击者盗用你的身份,以你的名义向第三方网站发送恶意请求。CRSF能做的事情包括利用你的身份发邮件,发短信,进行交易转账,甚至盗取账号信息。

如何防范?

所以:

文件上传漏洞是如何发生的?

文件上传漏洞,指的是用户上传一个可执行的脚本文件,并通过此脚本文件获得了执行服务端命令的能力。富文本编辑器可能遭受此攻击,被攻击者上传恶意代码,有可能服务端就被人黑了。

如何防范?

加密算法(RSA、AES、MD5、SHA)

SHA即安全散列算法(Secure Hash Algorithm)。SHA其实是一个算法家族,由美国国家安全局(NSA)开发,有SHA1、SHA2、SHA3三类,目前SHA1已经被破解,使用比较广泛的是SHA2类。

SHA256算法原理 link

安全散列算法,即是将一段接收到的message通过哈希算法将其转换成固定位数的哈希值(也称消息摘要)。SHA256就是将message通过哈希算法计算得到一个256位的哈希值。