Linux网络与进程管理

Linux 专栏收录该内容
14 篇文章 0 订阅

本文主要介绍了网络与进程的相关内容以及在Linux上如何进行网络与进程管理,包括以太网介绍,TCP/IP,网络分层模型,IP地址的规划;同时介绍了Linux内核在进程管理方面的相关机制

一、网络基础

此处的网络指以太网(Ethernet),它由Xerox的PARK实验室研发,并且免费提供

关于网络我们并不陌生,故此处仅作简要介绍

1. 网络分层模型

在网络诞生初期,只有同一厂商生产的设备可能相互通信,为打破这种窘境,20世纪70年代末,ISO(International Organization for Standardization,国际标准化组织)设计了OSI(Open System Interconnection,开放系统互联)参考模型,而如今大量使用的,我们将其称为TCP/IP协议栈,即DoD模型

OSI参考模型

OSI(Open System Interconnection,开放系统互联),是一种概念模型,故将其称为“参考模型”,定义于ISO/IEC 7498-1。它旨在以协议的形式帮助不同厂商的设备进行相互通信

设计思想

  • 将网络通信的过程划分为更小、更简单的组件,有助于开发、设计与排障等

  • 通过标准化网络组件,让多家厂商能够协同开发

  • 定义了模型每层执行的功能,从而鼓励了行业标准化

  • 让不同类型的网络硬件与软件能够彼此通信

  • 避免对一层的修改影响到其他层

OSI模型

再次说明,该模型并非具体的协议,它是一种思想,是指导原则,开发人员可根据该思想可开发能够实现网络互连的应用

该模型包含7层,其中上3层指定了终端中的应用如何彼此通信以及如何与用户交互,属于资源子网(Resources Subnet)的范畴;而下4层定义了如何进行端到端的数据传输,属于通信子网(Communication Subnet)

应用层
表示层
会话层
传输层
网络层
数据链路层
物理层
第7层 应用层

应用层(Application Layer)提供为应用软件而设的接口,以设置与另一应用软件之间的通信。例如: HTTP,HTTPS,FTP,TELNET,SSH,SMTP,POP3等。

第6层 表达层
主条目:表达层
表达层(Presentation Layer)把数据转换为能与接收者的系统格式兼容并适合传输的格式。

第5层 会话层

会话层(Session Layer)负责在数据传输中设置和维护计算机网络中两台计算机之间的通信连接。

第4层 传输层

传输层(Transport Layer)把传输表头(TH)加至数据以形成数据包。传输表头包含了所使用的协议等发送信息。例如:传输控制协议(TCP)等。

第3层 网络层

网络层(Network Layer)决定数据的路径选择和转寄,将网络表头(NH)加至数据包,以形成分组。网络表头包含了网络数据。例如:互联网协议(IP)等。

第2层 数据链路层

数据链路层(Data Link Layer)负责网络寻址、错误侦测和改错。当表头和表尾被加至数据包时,会形成帧。数据链表头(DLH)是包含了物理地址和错误侦测及改错的方法。数据链表尾(DLT)是一串指示数据包末端的字符串。例如以太网、无线局域网(Wi-Fi)和通用分组无线服务(GPRS)等。

分为两个子层:LLC(logical link control,逻辑链路控制)子层和MAC(media access control,介质访问控制)子层。

第1层 物理层

物理层(Physical Layer)在局部局域网上传送数据帧(data frame),它负责管理计算机通信设备和网络媒体之间的互通。包括了针脚、电压、线缆规范、集线器、中继器、网卡、主机接口卡等。

每一层都有其实现的协议,如

OSI

数据封装

数据包利用网络在不同设备之间传输时,为了可靠和准确地发送到目的地,并且高效地利用传输资源(传输设备和传输线路),事先要对数据包进行拆分和打包,在所发送的数据包上附加上目标地址,本地地址,以及一些用于纠错的字节,安全性和可靠性较高时,还要进行加密处理等等。这些操作就叫数据封装(Data Encapsulation)

OSI模型每一层都对数据进行封装来形成PDU(Protocol Data Unit,协议数据单元),PDU包含来自上层的信息和当前层的实体附加的信息,这个PDU会被传送到下一较低的层

每一层附加到PDU上的信息,是指定给另一个系统的同等层的,这就是对等层进行一次通信会话协调的过程,即

对等层通信

而其中每层的 PDU 一般由本层的协议头、协议尾和数据封装构成

数据封装的过程大致如下:
  1. 用户信息转换为数据,以便在网络上传输
  1. 数据转换为数据段,并在发送方和接收方主机之间建立一条可靠的连接
  1. 数据段转换为数据包或数据报,并在报头中放上逻辑地址,这样每一个数据包都可以通过互联网络进行传输
  1. 数据包或数据报转换为帧,以便在本地网络中传输。在本地网段上,使用硬件地址唯一标识每一台主机。
  1. 帧转换为比特流,并采用数字编码和时钟方案

数据封包

而数据解封与此相反

  • 在传输层用TCP头已标示了与一个特定应用的连接,并将数据封装成了数据段(Segment)

  • 网络层则用IP头标示了已连接的设备网络地址,并可基于此信息进行网络路径选择,此时将数据封装为数据包(Package)

  • 到了数据链路层,数据已封装成了数据帧(Frame),并用MAC头给出了设备的物理地址,当然还有数据校验等功能字段等

  • 到了物理层,则已封装成为比特流(Bit),就成为纯粹的物理连接了
    Data_Encapsulation

TCP/IP协议栈

互联网协议套件(英语:Internet Protocol Suite,缩写IPS)是一个网络通信模型,以及一整个网络传输协议家族,为网际网络的基础通信架构。它常被通称为TCP/IP协议族(英语:TCP/IP Protocol Suite,或TCP/IP Protocols),简称TCP/IP

因为该协议家族的两个核心协议:TCP(传输控制协议)和IP(网际协议),为该家族中最早通过的标准。由于在网络通讯协议普遍采用分层的结构,当多个层次的协议共同工作时,类似计算机科学中的堆栈,因此又被称为TCP/IP协议栈(英语:TCP/IP Protocol Stack) 。这些协议最早发源于美国国防部(缩写为DoD)的ARPA网项目,因此也被称作DoD模型(DoD Model)。这个协议族由互联网工程任务组负责维护

它将软件通信过程抽象化为四个抽象层,采取协议堆栈的方式,分别实现出不同通信协议。协议族下的各种协议,依其功能不同,被分别归属到这四个层次结构之中,常被视为是简化的七层OSI模型

应用层
传输层
网络互联层
网络访问(链接)层

应用层

应用层(application layer)包括所有和应用程序协同工作,利用基础网络交换应用程序专用的数据的协议。 应用层是大多数普通与网络相关的程序为了通过网络与其他程序通信所使用的层。这个层的处理过程是应用特有的;数据从网络相关的程序以这种应用内部使用的格式进行传送,然后被编码成标准协议的格式

一些特定的程序被认为运行在这个层上。它们提供服务直接支持用户应用。这些程序和它们对应的协议包括HTTP(万维网服务)、FTP(文件传输)、SMTP(电子邮件)、SSH(安全远程登陆)、DNS(名称<-> IP地址寻找)以及许多其他协议。 一旦从应用程序来的数据被编码成一个标准的应用层协议,它将被传送到IP栈的下一层

在传输层,应用程序最常用的是TCP或者UDP,并且服务器应用程序经常与一个公开的端口号相联系。服务器应用程序的端口由互联网号码分配局(IANA)正式地分配,但是现今一些新协议的开发者经常选择它们自己的端口号。由于在同一个系统上很少超过少数几个的服务器应用,端口冲突引起的问题很少。应用软件通常也允许用户强制性地指定端口号作为运行参数

链接外部的客户端程序通常使用系统分配的一个随机端口号。监听一个端口并且通过服务器将那个端口发送到应用的另外一个副本以创建对等链接(如IRC上的dcc文件传输)的应用也可以使用一个随机端口,但是应用程序通常允许定义一个特定的端口范围的规范以允许端口能够通过实现网络地址转换(NAT)的路由器映射到内部

传输层

传输层(transport layer)的协议,能够解决诸如端到端可靠性(“数据是否已经到达目的地?”)和保证数据按照正确的顺序到达这样的问题。在TCP/IP协议组中,传输协议也包括所给数据应该送给哪个应用程序。 在TCP/IP协议组中技术上位于这个层的动态路由协议通常被认为是网络层的一部分;一个例子就是OSPF(IP协议89)

TCP(IP协议6)是一个“可靠的”、面向链接的传输机制,它提供一种可靠的字节流保证数据完整、无损并且按顺序到达。TCP尽量连续不断地测试网络的负载并且控制发送数据的速度以避免网络过载。另外,TCP试图将数据按照规定的顺序发送。这是它与UDP不同之处,这在实时数据流或者路由高网络层丢失率应用的时候可能成为一个缺陷

较新的SCTP也是一个“可靠的”、面向链接的传输机制。它是面向纪录而不是面向字节的,它在一个单独的链接上提供通过多路复用提供的多个子流。它也提供多路自寻址支持,其中链接终端能够被多个IP地址表示(代表多个实体接口),这样的话即使其中一个连接失败了也不中断。它最初是为电话应用开发的(在IP上传输SS7),但是也可以用于其他的应用

UDP(IP协议号17)是一个无链接的数据报协议。它是一个“尽力传递”(best effort)或者说“不可靠”协议——不是因为它特别不可靠,而是因为它不检查数据包是否已经到达目的地,并且不保证它们按顺序到达。如果一个应用程序需要这些特性,那它必须自行检测和判断,或者使用TCP协议。 UDP的典型性应用是如流媒体(音频和视频等)这样按时到达比可靠性更重要的应用,或者如DNS查找这样的简单查询/响应应用,如果创建可靠的链接所作的额外工作将是不成比例地大

DCCP当前正由IEFT开发。它提供TCP流动控制语义,但对于用户来说保留UDP的数据报服务模型。 TCP和UDP都用来支持一些高层的应用。任何给定网络地址的应用通过它们的TCP或者UDP端口号区分。根据惯例使一些大众所知的端口与特定的应用相联系。 RTP是为如音频和视频流这样的实时数据设计的数据报协议。RTP是使用UDP包格式作为基础的会话层,然而据说它位于因特网协议栈的传输层。

网络互连层

TCP/IP协议族中的网络互连层(internet layer)在OSI模型中叫做网络层(network layer)。

正如最初所定义的,网络层解决在一个单一网络上传输数据包的问题。类似的协议有X.25和ARPANET的Host/IMP Protocol。 随着因特网思想的出现,在这个层上添加附加的功能,也就是将数据从源网络传输到目的网络。这就牵涉到在网络组成的网上选择路径将数据包传输,也就是因特网。 在因特网协议组中,IP完成数据从源发送到目的的基本任务

IP能够承载多种不同的高层协议的数据;这些协议使用一个唯一的IP协议号进行标识。ICMP和IGMP分别是1和2。 一些IP承载的协议,如ICMP(用来发送关于IP发送的诊断信息)和IGMP(用来管理多播数据),它们位于IP层之上但是完成网络层的功能,这表明因特网和OSI模型之间的不兼容性。所有的路由协议,如BGP、OSPF、和RIP实际上也是网络层的一部分,尽管它们似乎应该属于更高的协议栈

网络访问(链接)层

网络访问(链接)层(Network Access(link) layer)实际上并不是因特网协议组中的一部分,但是它是数据包从一个设备的网络层传输到另外一个设备的网络层的方法。这个过程能够在网卡的软件驱动程序中控制,也可以在韧体或者专用芯片中控制。这将完成如添加报头准备发送、通过实体介质实际发送这样一些数据链路功能

另一端,链路层将完成数据帧接收、去除报头并且将接收到的包传到网络层。 然而,链路层并不经常这样简单。它也可能是一个虚拟专有网络(VPN)或者隧道,在这里从网络层来的包使用隧道协议和其他(或者同样的)协议组发送而不是发送到实体的接口上。VPN和信道通常预先建好,并且它们有一些直接发送到实体接口所没有的特殊特点(例如,它可以加密经过它的数据)。由于现在链路“层”是一个完整的网络,这种协议组的递归使用可能引起混淆。但是它是一个实现常见复杂功能的一个优秀方法。(尽管需要注意预防一个已经封装并且经隧道发送下去的数据包进行再次地封装和发送)

OSI模型与TCP/IP模型的对比

下图为二者的各层的大致对应关系

OSI_DoD

2. CSMA/CD

CSMA/CD(Carrier-Sense Multiple Access with Collision Detection,带有冲突检测的载波侦听多路访问)是以太网使用的重要机制,这是一种帮助设备均衡地共享带宽的协议,可避免两台设备同时在网络介质上传输数据

如图,主机与通过网络传输数据时,首先检测线路上是否有数字信号,若没有其他主机传输数据,该主机将开始传输数据,并且在传输过程中,传输主机将持续监听线路,确保没有其他主机开始传输

CD

若该主机在线路上检测到其他信号,将发送一个扩展的拥堵信号(Jam Signal),使网段上的所有节点都不再发送数据。检测到拥堵信号后,其他节点将等待一段时间再尝试传输。后退算法决定了发生冲突的工作站多长时间后可重新传输

该机制工作大致流程为:

CSMA/CD

3. 协议首部

此处将重要的协议首部列出,以供参考

IPv4首部

IPv4_Header

TCP首部

TCP_Header

UDP首部

UDP Header
Offsets Octet 0 1 2 3
Octet Bit 0 1 2 3 4 5 6 7 8 910111213141516171819202122232425262728293031
0  0 Source portDestination port
4 32 LengthChecksum

IPv4伪头部

当UDP运行在IPv4之上时,为了能够计算校验和,需要在UDP数据包前添加一个“伪头部”。伪头部包括了IPv4头部中的一些信息,但它并不是发送IP数据包时使用的IP数据包的头部,而只是一个用来计算校验和而已

IPv4 Pseudo Header Format
Offsets Octet 0 1 2 3
Octet Bit 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
0 0 Source IPv4 Address
4 32 Destination IPv4 Address
8 64 Zeroes Protocol UDP Length
12 96 Source Port Destination Port
16 128 Length Checksum
20 160+ Data

帧首部

在实际应用中,大多数应用的以太网数据包是Ethernet V2的帧(如HTTP、FTP、SMTP、POP3等应用),而交换机之间的BPDU(Bridge Protocol Data Unit,桥协议数据单元)数据包则是IEEE-802.3的帧,VLAN Trunk协议如802.1Q和Cisco的CDP(Cisco Discovery Protocol,思科发现协议)等则是采用IEEE-802.3 SNAP的帧

Frame_Header

4. TCP连接

上文已有介绍,TCP(Transmission Control Protocol,传输控制协议),是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能

TCP建立连接

我们习惯上将TCP连接描述为三次握手与四次断开,如下图

三次握手与四次断开

三次握手
  • 第一次握手:建立连接。客户端发送连接请求报文段,将SYN位置为1,Sequence Number为x;然后,客户端进入SYN_SEND状态,等待服务器的确认;
  • 第二次握手:服务器收到SYN报文段。服务器收到客户端的SYN报文段,需要对这个SYN报文段进行确认,设置Acknowledgment Number为x+1(Sequence Number+1);同时,自己自己还要发送SYN请求信息,将SYN位置为1,Sequence Number为y;服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发送给客户端,此时服务器进入SYN_RECV状态;
  • 第三次握手:客户端收到服务器的SYN+ACK报文段。然后将Acknowledgment Number设置为y+1,向服务器发送ACK报文段,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手。
四次断开
  • 第一次分手:主机1(可以是客户端,也可以是服务器端),设置Sequence Number和Acknowledgment Number,向主机2发送一个FIN报文段;此时,主机1进入FIN_WAIT_1状态;这表示主机1没有数据要发送给主机2了;
  • 第二次分手:主机2收到了主机1发送的FIN报文段,向主机1回一个ACK报文段,Acknowledgment Number为Sequence Number加1;主机1进入FIN_WAIT_2状态;主机2告诉主机1,我“同意”你的关闭请求;
  • 第三次分手:主机2向主机1发送FIN报文段,请求关闭连接,同时主机2进入LAST_ACK状态;
  • 第四次分手:主机1收到主机2发送的FIN报文段,向主机2发送ACK报文段,然后主机1进入TIME_WAIT状态;主机2收到主机1的ACK报文段以后,就关闭连接;此时,主机1等待2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,主机1也可以关闭连接了。

TCP FSM

FSM(Finite State Machine,有限状态机)又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型

TCP FSM即TCP有限状态机,可以描述为TCP连接的“生命阶段”。一个TCP设备与另一个TCP设备之间的每个连接在没有连接的空状态下开始,然后继续通过一系列状态直到建立连接。它保持在该状态,直到某些事情发生导致连接再次关闭,此时它继续通过另一个过渡状态序列并返回到关闭状态

TCP FSM状态

TCP FSM状态1

状态描述
CLOSED起始点,在超时或者连接关闭时候进入此状态,这并不是一个真正的状态,而是这个状态图的假想起点和终点
LISTEN服务器端等待连接的状态。服务器经过 socket,bind,listen 函数之后进入此状态,开始监听客户端发过来的连接请求。此称为应用程序被动打开(等到客户端连接请求)
SYN-SENT第一次握手发生阶段,客户端发起连接。客户端调用 connect,发送 SYN 给服务器端,然后进入 SYN_SENT 状态,等待服务器端确认(三次握手中的第二个报文)。如果服务器端不能连接,则直接进入CLOSED状态
SYN-RECEIVED第二次握手发生阶段,跟SYN-SENT对应,这里是服务器端接收到了客户端的 SYN,此时服务器由 LISTEN 进入 SYN_RCVD状态,同时服务器端回应一个 ACK,然后再发送一个 SYN 即 SYN+ACK 给客户端。状态图中还描绘了这样一种情况,当客户端在发送 SYN 的同时也收到服务器端的 SYN请求,即两个同时发起连接请求,那么客户端就会从 SYN_SENT 转换到 SYN_REVD 状态
ESTABLISHED第三次握手发生阶段,客户端接收到服务器端的 ACK 包(ACK,SYN)之后,也会发送一个 ACK 确认包,客户端进入 ESTABLISHED 状态,表明客户端这边已经准备好,但TCP 需要两端都准备好才可以进行数据传输。服务器端收到客户端的 ACK 之后会从 SYN_RCVD 状态转移到 ESTABLISHED 状态,表明服务器端也准备好进行数据传输了。这样客户端和服务器端都是 ESTABLISHED 状态,就可以进行后面的数据传输了。所以 ESTABLISHED 也可以说是一个数据传送状态
FIN-WAIT-1第一次关闭。主动关闭的一方(执行主动关闭的一方既可以是客户端,也可以是服务器端),终止连接时,发送 FIN 给对方,然后等待对方返回 ACK 。调用 close() 第一次关闭就进入此状态
CLOSE-WAIT接收到FIN 之后,被动关闭的一方进入此状态。具体动作是接收到 FIN,同时发送 ACK。之所以叫 CLOSE_WAIT 可以理解为被动关闭的一方此时正在等待上层应用程序发出关闭连接指令。TCP关闭是全双工过程,这里客户端执行了主动关闭,被动方服务器端接收到FIN 后也需要调用 close 关闭,这个 CLOSE_WAIT 就是处于这个状态,等待发送 FIN,发送了FIN 则进入 LAST_ACK 状态
FIN-WAIT-2主动端先执行主动关闭发送FIN,然后接收到被动方返回的 ACK 后进入此状态
LAST-ACK被动方发起关闭请求,由状态CLOSE-WAIT进入此状态,具体动作是发送 FIN给对方,同时在接收到ACK 时进入CLOSED状态
CLOSING两边同时发起关闭请求时(即主动方发送FIN,等待被动方返回ACK,同时被动方也发送了FIN,主动方接收到了FIN之后,发送ACK给被动方),主动方会由FIN_WAIT_1 进入此状态,等待被动方返回ACK
TIME-WAIT共有三个状态会进入该状态:
● 由CLOSING进入:同时发起关闭情况下,当主动端接收到ACK后,进入此状态,实际上这里的同时是这样的情况:客户端发起关闭请求,发送FIN之后等待服务器端回应ACK,但此时服务器端同时也发起关闭请求,也发送了FIN,并且被客户端先于ACK接收到

● 由FIN_WAIT_1进入:发起关闭后,发送了FIN,等待ACK的时候,正好被动方也发起关闭请求,发送了FIN,这时客户端接收到了先前ACK,也收到了对方的FIN,然后发送ACK(对对方FIN的回应),与CLOSING进入的状态不同的是接收到FIN和ACK的先后顺序

● 由FIN_WAIT_2进入:这是不同时的情况,主动方在完成自身发起的主动关闭请求后,接收到了对方发送过来的FIN,然后回应 ACK

各状态之间的转换如下图

TCP_FSM

5. IP

我们之前有提到过,数据在传输时,经过通信子网的每一层都会添加相应协议的首部,而其中有一个重要信息,即源地址与目标地址,用于记录通信双方

而在不同的层中,“地址”的概念亦不相同,如

  • 在传输层,通过端口标记主机上的进程
  • 在网络层,通过IP标记主机三层信息
  • 在数据链路层,通过MAC来标记主机二层信息

此处将对IP做简要介绍

网际协议

IP(Internet Protocol),网际协议,也称为互联网协议。是在TCP/IP协议族中网络层的主要协议,任务仅仅是根据源主机和目的主机的地址来传送数据。为此目的,IP定义了寻址方法和数据报的封装结构。现有IPv4IPv6两个版本,此处介绍IPv4

该协议工作在网络层,而该层的其他协议可以说都是为其提供支持的。数据在IP互联网中传送时会被封装为数据包

IP提供了一种“不可靠的”数据包传输机制(也被称作“尽力而为”或“尽最大努力交付”);也就是说,它不保证数据能准确的传输。数据包在到达的时候可能已经损坏,顺序错乱(与其它一起传送的报文相比),产生冗余包,或者全部丢失。如果应用需要保证可靠性,一般需要采取其他的方法,例如利用IP的上层协议控制

IP地址

互联网协议地址(Internet Protocol Address)又译为网际协议地址,是分配给网络上使用网际协议(IP) 的设备的数字标签。常见的IP地址分为IPv4IPv6两大版本

从某种意义上说,IP(网际协议)是“掌控全局”的,它了解所有互联的网络,这是因为网络中的所有设备都有一个逻辑地址,这就是IP地址,IP是软件地址,而非硬件地址,硬件地址被硬编码到NIC(Network Interface Card)中,用于在本地网络中寻找主机(即MAC)

层次型IP编址

IPv4地址长32位,被划分为4组,可使用三种方式表示

  • 点分十进制表示,如172.16.30.56
  • 二进制表示,如10101100.00010000.00011110.00111000
  • 十六进制表示,如AC.10.1E.38

以上例子中表示的是同一个地址,日常中我们常用点分十进制与二进制表示

而若按照IP的设计,一共有 2 32 2^{32} 232个地址,将其按照一层逻辑结构编址,在路由选择时将非常低效,鉴于此,我们将IP地址分为网络地址主机地址(想象一下电话号码的区号)

网络地址唯一标识网络,在同一网络中,所有主机的IP地址都有相同的网络地址,而同一个网络内部的特定主机都有唯一为主机地址。如,对于192.168.1.10,192.168.1就是网络地址,10就是主机地址。而我只如何知道的呢?

网络分类

最初人们工具网络规模创建网络分类,即对于少量包含大量节点的网络,创建了A类网络;另一种底端情况,创建了C类网络,即大量包含少量节点的网络,具体划分如下所示

类别最大网络数IP地址范围单个网段最大主机数
A126(27-2)1.0.0.0-127.255.255.25516777214
B16384(214)128.0.0.0-191.255.255.25565534
C2097152(221)192.0.0.0-223.255.255.255254

即二进制的IP地址为0开头的为A类网络,10开头的为B类网络,110的为C类网络

此外还有:1110开头的为D类网络,即224-239,为组播地址;1111开头的为E类地址,即240-255,用于科研,D类与E类网络我们这里用到不多

私有IP地址

IP地址在设计之初,提供了私有IP地址,这些地址在互联网中不可被路由,同时也节省了IP地址空间,对于A、B、C类网络都有其私有IP地址,如下所示

IP地址区段IP数量分类网络说明最大CIDR区块(子网掩码)主机端位长
10.0.0.0–10.255.255.25516777216单个A类网络10.0.0.0/8 (255.0.0.0)24位
172.16.0.0–172.31.255.255104857616个连续B类网络172.16.0.0/12 (255.240.0.0)20位
192.168.0.0–192.168.255.25565,536256个连续C类网络192.168.0.0/16 (255.255.0.0)16位

子网划分

上文提到了网络分类,但有时由于各种原因,我们需要对网络进行再次分隔,即子网划分

比如,当一组IP地址指定给一个公司时,公司可能将该网络“分割成”小的网络,每个部门一个。这样,技术部门和管理部门都可以有属于它们的小网络。通过划分子网,我们可以按照我们的需要将网络分割成小网络。这样也有助于降低流量和隐藏网络的复杂性

划分子网后,通过使用掩码,把子网隐藏起来,使得从外部看网络没有变化,这就是子网掩码

子网掩码

子网掩码(Subnet Mask)又叫网络掩码、地址掩码、子网络遮罩,它是一种用来指明一个IP地址的哪些位标识的是主机所在的子网,以及哪些位标识的是主机的位掩码。子网掩码不能单独存在,它必须结合IP地址一起使用,即将某个IP地址划分成网络地址和主机地址两部分

并非所有网络都需要子网,故网络可以使用其默认的子网掩码

而上文的实例中,我们之所以能区分一个C类网络的网络地址与主机地址,就是这个原因,各类网络的默认子网掩码如下所示

网络格式默认子网掩码
A类network.node.node.node255.0.0.0
B类network.network.node.node255.255.0.0
C类network.network.network.node255.255.255.0

VLSM

VLSM(Variable Length Subnet Mask,可变长子网掩码)使用长度不同的子网掩码将网络划分为众多子网,适用于不同类型的网络设计,其主要实现为使用CIDR(Classless Inter-Domain Routing,无类别域间路由)和路由汇聚(route summary)来控制路由表的大小

CIDR

我们从ISP那里获取到的IP类似于*192.168.10.32/28,这里指出了子网掩码,即使用/来指出子网掩码中有多少位1,显然,其最大值为/32

A类网络的默认子网掩码为255.0.0.0,第一个字节全为1,即11111111,用CIDR表示法就是/8,下表列出了一些子网掩码与CIDR表示法

子网掩码CIDR值
255.0.0.0/8
255.128.0.0/9
255.192.0.0/10
255.224.0.0/11
255.240.0.0/12
255.248.0.0/13
255.255.0.0/16
255.255.128.0/17
255.255.192.0/18
255.255.255.0/24
255.255.255.128/25

如,C类网络192.168.10.0/25

  • 子网数:在128(10000000)中,取值为1的位数为1,因此有21=2个子网

  • 每个子网中有多少主机:有7个主机位取值为0(10000000),主机数为27-2=126个主机,减去的2个为子网地址与广播地址,他们不是合法的主机地址

  • 有哪些子网:网络位可为10,故合法的网络位为0128

  • 每个子网的广播地址:有两个子网,192.168.10.0/25192.168.10.128/25对于第一个子网,所有主机位为1为广播地址,即192.168.10.127/25,对于第二个子网,则为192.168.10.255/25

  • 每个子网的合法主机地址:

    0128
    第一个地址1129
    最后一个地址126254
    广播地址127255

100.0.0.16/28对应网段的网络地址、广播地址、可分配IP地址范围:

  • 该地址将IP的第四段的4位作为网络地址,故其网络地址为100.0.0.16

  • 广播地址为主机位全部置1,即100.0.0.31

  • 该网络可用的IP地址为100.0.0.17100.0.0.30

路由聚合

路由汇聚(route summary)可以让路由器选择协议能后用一个地址通告众路由器,旨在减小路由器中路由表的大小,,缩短IP对路由选择表进行分析以找出前往远程网络的路径所需的时间

例如,现有网络192.168.16.0~192.168.31.0,其中有16个C类网络,而24刚好为16,而C类网络子网掩码第三字节默认为8位,我们需要再分4位来作为主机位,故其子网掩码为24-4=20位,即255.255.240.0


二、Linux网络管理

1. 网络设备的表示

所谓的网络设备,对于主机而言,主要就是网络接口卡了,其在Linux系统的命名方式如下

CentOS 6:传统命名方式
lo :本地回环接口
eth#: 以太网设备,eth1,eth2,…
ppp#: 点对点网络,ppp0,ppp1,…

此处主要介绍CentOS 7的命名方式

CentOS 7:可预测功能的命名机制

  • systemd对网络设备的命名方式

    • (a)若firmware或BIOS为主板上集成的设备提供的索引信息可用,且可预测,则根据此索引命名,如eno1

    • (b)若Firmware或BIOS为PCI-E扩展槽所提供的索引信息可用,且可预测,则根据此索引命名,如ens1

    • (c)若硬件接口的物理位置信息可用,则根据此信息进行命名,如enp2s0

    • (d)若用户显式启用,也可根据MAC地址进行命名,如enxc821583e4379

    • (e)上述均不可用时,则使用传统命名机制,如eth0,eth1

      上述命名机制中,有的需要biosdevname程序的参与

  • 名称组成格式

    • en:Ethernet

    • wl:wlan

    • ww:wwan(无线广域网)

    • 名称类型:

      o:集成设备的设备索引号

      s:扩展槽的索引号

      x:基于MAC地址命名

      ps:PCI总线上的插槽上的设备,如enp2s1,即第2个PCI总线上第1个插槽上的设备

  • 网卡设备的命名过程

    1. udev,辅助工具程序:/lib/udev/rename_device,会根据/usr/lib/udev/rules.d/60-net.rules文件中的信息,查询/etc/sysconfig/network-scripts/ifcfg-开头的文件,查找HWADDR,将于实际设备的MAC地址对应的配置文件中DEVICE的值设定为设备名

    2. 若第一步命名操作没有发生,且安装了biosdevname,biosdevname会根据/usr/lib/udev/rule.d/71-biosdevname.rules中定义的规则对网络接口命名

    3. 若第一第二步没有发生,通过检测网络接口设备,根据/usr/lib/udev/rules.d/75-net-description中的规则进行命名
      ID_NET_NAME_ONBOAR
      ID_NET_NAME_SLOT
      ID_NET_NAME_PATH

  • 如何回归传统命名方式

    1. 编辑/etc/default/grub配置文件
      GRUB_CMDLINE_LINUX参数加上一项net.ifnames=0

    2. 为grub2生成配置文件
      grub2-mkconfig -o /etc/grub2.cfg

    3. 重启系统

另外, 可以使用设备名来直接引用设备

  • 在红帽5中,网络设备名称使用别名,在/etc/modprobe.conf文件中

  • 在红帽6中,在/etc/udev/rules.d目录中的70-persistent-net.rules文件中定义

装卸载网卡驱动

  • 卸载:modprobe -r MOD
  • 装载:modprobe MOD

2. Linux网络配置工具

在介绍配置之前,先了解一个概念:对应Linux而言,IP地址是属于内核的,因此只要当前系统有这个地址,不管他人从哪个网卡传入数据(如ping),内核都会响应

另外,这里先各工具与方式作以简要总结

  • 静态指定
    • net-tools

      • ifconfig:配置IP

      • route:路由

      • netstat:状态

    • iproute2

      • ip OBJECT {link,addr,route},ss,tc
    • nm(CentOS 7)

      • nmcli,nmtui
    • DNS服务器指定

      • 配置文件:/etc/resolv.conf
    • 本地主机名配置

      • hostname

      • 配置文件:/etc/sysconfig/network

      • CentOS7:hostnamectl

RedHat相关发行版网络配置文件
/etc/sysconfig/network-scripts/ifcfg-NETCARD_NAME

  • 动态获取
    • DHCP

ifconfig

ifconfig即网卡配置(network InterFace CONFIG),其常用格式为

ifconfig [-v] [-a] [-s] [interface]
	-v			显示详细信息
	-a			显示所有接口信息,默认仅显示启用的网卡
	-s			使用端类表形式显示

ifconfig InterFace IP/MASK [up|down]
MASK
	长格式: ifconfig InterFace IP netmask MASK
	CIDR: ifconfig InterFace IP/MASK
ifconfig [-v] [-a] [-s] [interface]
该方式用于显示接口的相关信息,如
[root@localhost ~]# ifconfig
eno16777736: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.18.128  netmask 255.255.255.0  broadcast 192.168.18.255
        inet6 fe80::20c:29ff:fecf:6af3  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:cf:6a:f3  txqueuelen 1000  (Ethernet)
        RX packets 335  bytes 32866 (32.0 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 301  bytes 35913 (35.0 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 0  (Local Loopback)
        RX packets 20  bytes 1956 (1.9 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 20  bytes 1956 (1.9 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@localhost ~]# ifconfig -s
Iface      MTU    RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR Flg
eno16777  1500      364      0      0 0           317      0      0      0 BMRU
lo       65536       20      0      0 0            20      0      0      0 LRU
[root@localhost ~]# ifconfig -v eno16777736
eno16777736: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.18.128  netmask 255.255.255.0  broadcast 192.168.18.255
        inet6 fe80::20c:29ff:fecf:6af3  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:cf:6a:f3  txqueuelen 1000  (Ethernet)
        RX packets 419  bytes 39824 (38.8 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 347  bytes 42103 (41.1 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
        
显示的字段为:
  • Scope:地址的作用范围
  • RX packet:接收到的报文个数,TX packets:传出的报文的个数
    • errors:错误的个数
    • ropped:丢弃的个数
    • overruns:溢出的个数
    • frame:帧数
  • collisions:冲突
  • txqueuelen:传输队列的长度
  • RX bytes:收到的字节数
  • TX bytes:传出的字节数
  • Interrupt:中断
ifconfig InterFace IP/MASK [up|down]
该方式配置的地址立即送往内核中的TCP/IP协议栈,配置立即生效,但重启网络服务或主机,都失效
一块网卡使用多个地址
  • 网络设备可以别名,如:
    • ethX:X, eth0:0, eth0:1, …

    • 配置方法:
      ifconfig ethX:X IP/NETMASK 不会永久有效
      /etc/sysconfig/network-scripts/ifcfg-ethX:X
      DEVICE=ethX:X

    • Tips:非主要地址不能使用DHCP动态获取,即别名不能使用DHCP

route

该命令用于查看或维护路由表,支持子命令,不带任何选项的route命令用于查看本机的路由表:

[root@localhost ~]# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         192.168.18.2    0.0.0.0         UG    100    0        0 eno16777736
192.168.18.0    0.0.0.0         255.255.255.0   U     0      0        0 eno16777736
192.168.18.0    0.0.0.0         255.255.255.0   U     100    0        0 eno16777736

这里对Flags字段做以说明

Flages意义
Uroute is up,启用状态
Htarget is a host,主机路由
Guse gateway,网关路由
Rreinstate route for dynamic routing
Ddynamically installed by daemon or redirect
Mmodified from routing daemon or redirect
Ainstalled by addrconf
Ccache entry
!reject route

而查看路由表时,可以使用-n选项,以数字方式显示各主机或端口等相关信息,不反解地址到主机名

而对于子命令,这里介绍adddel

add:添加
	-host 主机路由
	-net 网络路由
		-net 0.0.0.0 默认路由

	route add -net|-host DEST gw NEXTHOP|dev DEVICE,如
		# route add -net 10.0.0.0/8 gw 192.168.10.1 dev eth1
		# route add -net 0.0.0.0/0.0.0.0 gw 192.168.10.1
		# route add default gw 192.168.10.1
	route add default gw NEXTHOP	添加默认路由

del:删除
	-host 主机路由
	-net 网络路由
	不会引起混淆时,gw可省略

	route del -net|-host DEST,如
		# route del -net 10.0.0.0/8
	route del default	删除默认路由

所做出的改动立即生效,重启网络服务或主机后失效

ifcfg

这是脚本,用于简单设置网络接口参数,其用法比较简答:

ifcfg [ DEVICE [ :ALIAS: ] ] [ command ] ADDRESS [ LENGTH ] [ PEER ]

另外,还有两个脚本实现的命令,ifupifdown,这两个命令通过配置文件/etc/sysconfig/network-scripts/ifcfg-IFACE来识别接口并完成配置,用法为

ifup CONFIG [boot]
ifdown CONFIG

ip


ip命令是iproute2家族的命令,该软件包(iproute2)版本与系统内核版本相关:

[root@localhost ~]# rpm -qi iproute
Name        : iproute
Version     : 3.10.0
Release     : 21.el7
Architecture: x86_64
Install Date: Thu 20 Dec 2018 04:13:41 AM CST
Group       : Applications/System
Size        : 1229304
License     : GPLv2+ and Public Domain
Signature   : RSA/SHA256, Sat 14 Mar 2015 03:56:08 PM CST, Key ID 24c6a8a7f4a80eb5
Source RPM  : iproute-3.10.0-21.el7.src.rpm
Build Date  : Fri 06 Mar 2015 11:07:32 AM CST
Build Host  : worker1.bsys.centos.org
Relocations : (not relocatable)
Packager    : CentOS BuildSystem <http://bugs.centos.org>
Vendor      : CentOS
URL         : http://kernel.org/pub/linux/utils/net/iproute2/
Summary     : Advanced IP routing and network device configuration tools
Description :
The iproute package contains networking utilities (ip and rtmon, for example)
which are designed to use the advanced networking capabilities of the Linux
2.4.x and 2.6.x kernel.
[root@localhost ~]# uname -r
3.10.0-229.el7.x86_64

net-tools工具较古老,且自2001年起,Linux社区已经对其停止维护,iproute2的出现旨在从功能上取代net-tools

net-tools通过procfs(/proc)和ioctl系统调用去访问和改变内核网络配置,而iproute2则通过netlink套接字接口与内核通讯。抛开性能而言,iproute2的用户接口比net-tools显得更加直观。比如,各种网络资源(如link、IP地址、路由和隧道等)均使用合适的对象抽象去定义,使得用户可使用一致的语法去管理不同的对象


iproute2工具的最主要的命令为ip,通过该命令,我们可以进行网络大部分管理工作,其使用格式为

ip [ OPTIONS ] OBJECT { COMMAND | help }

通过ip命令可以进行众多项目的管理,该命令将其分为众多OBJECT,如linkaddrroute

Tips

OBJECTCOMMAMD在不会引起混淆的情况下可以简写

ip link
ip link - network device configuration
	set
		ip link set DEV {up|down}
			dev NAME (default)		指明要管理的设备,dev关键字可省略;
			up|down					禁用或启用
			txqueuelen|txqlen		传输队列的长度
			multicast {on|off}		多播开关
			name NAME				重命名,应先停用接口
			mtu NUMBER				设置MTU的大小,默认为1500
			netns PID				ns为namespace,用于将接口移动到指定的网络名称空间

	 show/list
		[ dev IFACE ]				指定接口
		[ UP ]						仅显示处于激活状态的接口

如,禁用网卡

[root@localhost ~]# ip link set eno16777736 down

查看网卡信息

[root@localhost ~]# ip link show dev eno16777736
2: eno16777736: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
    link/ether 00:0c:29:cf:6a:f3 brd ff:ff:ff:ff:ff:ff
ip netns
ip netns - manage network namespaces
	ip netns list:列出所有的netns
	ip netns add NAME:创建指定的netns
	ip netns del NAME:删除指定的netns
	ip netns exec NAME COMMAND:在指定的netns中运行命令

[root@localhost ~]# ip netns add testns
[root@localhost ~]# ip netns list
testns
[root@localhost ~]# ip netns del testns
[root@localhost ~]# ip netns list
[root@localhost ~]#
ip address
ip address - protocol (IP or IPv6) address on a device
	ip address add IFACE_ADDR dev IFACE
		[ label LABEL ]:添加地址时指定网卡别名,如
			ip addr add 192.168.18.200/24 dev eno16777736 label eno16777736:1
		[ scope { global | link | host } ]:指定作用域
			global:全局可用
			link:仅链接可用
			host:本机可用
		[ broadcast ADDRESS ]:指定广播地址,会根据IP和NETMASK自动计算得到
		
	ip address delete - delete protocol address
		ip addr delete IFADDR dev IFACE
	
	ip address show - look at protocol addresses
		[ dev DEVICE ]
		[ label PATTERN ]
		[ primary | secondary ]
		
	ip address flush - flush protocol addresses
		ip addr flush dev IFACE:清空指定接口地址
ip route
ip route - routing table management
	ip route add - add new route
		ip route add
			添加路由:ip route add TARGET via GW dev IFACE src SOURCE_IP
				TARGET:
					主机路由:IP
					网络路由:NETWORK/MASK
				如:
					# ip route add 192.168.0.0/24  via 10.0.0.1  dev eth1 src  10.0.20.100
					
			添加网关:ip route add defalt via GW
		
	ip route change - change route
		ip  route change TYPE PREFIX  via GW  [dev  IFACE]  [src SOURCE_IP]
			TYPE:默认为unicast,下同
				blackhole:黑洞,报文会被丢弃
				unreachable:不可达
				prohibit:明确说明不通
				
			PREFIX :IP与掩码长度,如192.168.0.0/24,下同
		
	ip route replace - change or add new one
		ip  route   replace  TYPE PREFIX  via GW  [dev  IFACE]  [src SOURCE_IP]
	
	ip route delete - delete route
		删除路由:ip route del TYPE PREFIX
		
		如:
			ip route del 192.168.1.0/24
		
	ip route show - list routes
		TYPE PREFIX
	
	ip route flush - flush routing tables
		[ dev IFACE ]
		[ via PREFIX ]
		
	ip route get - get a single route
		ip route get TYPE PRIFIX
		
		如:
			ip route get 192.168.0.0/24

下图为net-tools与iproute2工具的命令对比

iproute2_net-tools

nmcli

在CentOS7中默认使用NetworkManager守护进程来监控和管理网络设置。nmcli是命令行的NetworkManager工具,会自动把配置写到/etc/sysconfig/network-scripts/目录

此外NetworkManager还提供一个TUI工具,即nmtui,该命令用法较为简单,此处不过多介绍,其配置界面如下

nmtui

此外,关于图形配置工具,还有setupsystem-config-network-gui,这些工具修改完成后,将直接修改网络配置文件,重新读取后生效


nmcli通过NetworkManager服务管理连接(connection)。一个接口(device)可以有多个连接(connection),但是同时只允许一个连接(connection)处于激活(active)状态

可以理解为,一个连接就是(connection)就是/etc/sysconfig/network-scripts/目录下的一个配置文件,接口(device)是物理设备,一个物理设置可以拥有多个配置文件,但只能有一个配置文件属于使用(active)状态;配置文件的生成与使用状态均由NetworkManager控制

nmcli命令的用法如下

nmcli  [ OPTIONS ] OBJECT { COMMAND | help }

OBJECT(可简写)
	device:show and manage network interfaces
	connection:show,stop,and manage network connections
	
	connection
		show [--active] [设备]
		up
		down
		add
		delete
		reload
		load
		modify
			modify [ id | uuid | path ] <ID> [+|-]<setting>.<property> <value>
			
			修改IP地址等属性
				nmcli connection modify IFACE [+|-]setting.property value
					setting.property:
						ipv4.address
						iv4.gateway
						ipv4.dns1
						ipv4.method
							manual
						…
			
	device
		status
		show
		connect
		disconnect

hostnamectl

该命令是CentOS7主机名称配置工具,用法如下

hostnamectl HOSTNAME					设定主机名,立即生效,重启网卡或主机后无效
hostnamectl status						显示当前主机名信息
hostnamectl set-hostname HOSTNAME		设定主机名,永久有效

此外,还可以通过hostname HOSTNAME命令进行配置,可立即生效,但不会永久有效,不带参数的hostname命令可查看本机主机名,如

[root@localhost ~]# hostname
localhost
[root@localhost ~]# hostnamectl status
   Static hostname: localhost
         Icon name: computer-vm
           Chassis: vm
        Machine ID: e394ee5b1fd740cbbbcdc10df183c1a0
           Boot ID: 272c377bf73940e5be255eed4315ad01
    Virtualization: vmware
  Operating System: CentOS Linux 7 (Core)
       CPE OS Name: cpe:/o:centos:centos:7
            Kernel: Linux 3.10.0-229.el7.x86_64
      Architecture: x86-64

3. 相关配置文件

关于网络配置文件,位于/etc/sysconfig/network-scripts/目录,分为两类:

  • 配置IP、掩码、网关、DNS:
    以太网: ifcfg-eth#
    PPP: ifcfg-ppp#
  • 配置路由
    以太网: route-eth#
    PPP: route-ppp#

网络接口配置文件

该文件为/etc/sysconfig/network-scripts/ifcfg-INTERFACE_NAME,可以使用文本编辑器修改,亦可通过上文介绍的配置修改命令修改,其各字段说明如下:

DEVICE="eth0"
	此配置关联至的设备,设备名要与文件ifcfg-后的内容保持一致
	
BOOTPROTO=none
	激活此接口时使用何种协议来配置接口属性
	引导协议:{none|static|dhcp|bootp}
	指定为none或static时,以下的配置才会生效
	
HWADDR="00:0C:29:26:62:92"
	对应设备的MAC地址:要与真实MAC地址保持一致,可省略
	
NM_CONTROLLED="yes"
	是否接受NetworkManager脚本控制:{yes|no},CentOS6建议为"no"
	
	网络服务:
		network
		NetworkManager
		
ONBOOT="yes"
	是否开机自动启动此网络设备{yes|no}
	
TYPE="Ethernet"
	设接口类型,如Etheraget Bridge
UUID="14351f7f-a726-4dfc-966e-dfb1f352f226"
	唯一标识,可省略
	
DOMAIN=
	DNS搜索域
	
IPADDR=
	ip地址
	
NETMASK=
	子网掩码,CentOS7支持使用PREFIX以长度方式指明自子网掩码
	
GATEWAY=
	默认网关
	
DNS1=
	DNS1服务地址,可指定DNS2,DNS3
	
IPV6INIT=no
	是否自动初始化IPv6协议地址
	
USERCTL=no
	是否允许普通用户启用或禁用此接口
	
PEERDNS={yes|no}
	若BOOTPROTO的值为“dhcp”,是否允许dhcp server分配的dns服务器指向更新/etc/resolv.conf中的(即手动指定)DNS服务器地址

此外,/etc/sysconfig/network文件可用于进行全局定义网络属性,而/etc/resolv.conf文件则为默认的DNS指向,即若/etc/sysconfig/network-scripts/ifcfg-INTERFACE_NAME文件中指定了相关信息,均会覆盖前二者中的定义

/etc/sysconfig/network文件定义方式与/etc/sysconfig/network-scripts/ifcfg-INTERFACE_NAME类似,一般地,我们将主机名配置在此处指定:HOSTNAME=,其他常用字段为

NETWORKING:是否启用本机的网络功能
NETWORKING_IPV6:是否启用本机的IPV6功能,即使是no,也不能彻底禁用IPV6,除非禁用IPV6模块
GATEWAY:定义网关,此处为全局的,若与网卡冲突,引网卡的方位小,以网卡为准

/etc/resolv.conf文件定义格式为nameserver DNS_SERVER_IP,最多可以配置三个

关于DNS,也可以指定为使用本地文件,即hosts,该文件为/etc/hosts,定义格式为2

主机IP	主机名	主机别名

配置修改完成后,需要重启网络服务生效:

  • CentOS6:

    service SERVICE {start|stop|restart|status}

    service network restart

    等效于执行:/etc/rc.d/init.d/network restart

  • CentOS7:

    systemctl {start|stop|restart|status} SERVICE[.service]

    systemctl restart network.service

路由配置文件

路由配置文件为/etc/sysconfig/network-scripts/route-IFACE

  • 添加格式1:每行一个路由条目
    DEST via NEXTHOP
  • 添加格式2: 每三行一个路由条目
      ADDRESS#=DEST
      NETMASk#=MASK
      GATEWAY#=Gateway
    

    一组的#应该使用相同的数字

    两种格式不能混合使用

4. 网络监测工具

ping

ping
	send ICMP ECHO_REQUEST to network hosts

	ping [OPTIONS] DESTINATION

		-c #			指定请求的次数
		-w DEADLINE		测试执行时长
		-W TIMEOUT		超时时长
		-s #			指定报文大小

traceroute

traceroute
	print the route packets trace to network host
	获取从当前主机到达目标主机所有经过的网关

	traceroute HOST

tracepath

tracepath
	traces path to a network host discovering MTU along this path

mtr

mtr
	a network diagnostic tool
	网络诊断工具

netstat

netstat
	Print network connections, routing tables, interface statistics, masquerade connections, and multicast memberships
	显示网络连接、路由表、接口统计,伪装连接连接和多播成员关系
	
	显示网络连接
		-t: tcp协议的连接,连接均有其状态,FSM(Finite State Machine)
		-u: udp协议的连接
		
		其他传输层协议:
			--udplite|-U
			--sctp|-S
			--raw|-w
		
		-l: 监听状态的连接
		-a: 所有状态的连接
		-p: 连接相关的进程及PID
		-n: 数字格式显示IP和端口
			--numeric-hosts:以数字形式显示主机
			--numeric-ports:以数据形式显示端口
			
		-e: 扩展格式信息
		-w: raw socket(裸套接字)相关

		常用组合
			netstat -tan
			netstat -uan
			netstat -tunl
			netstat -rn
			
	显示路由表
		-r: 显示内核路由表,类似于route或ip route show
		-n: 数字格式显示IP和端口
		
	显示接口统计数据
		netstat  {--route|-r} [--numeric|-n]
		netstat    {--interfaces|-I|-i}    [iface]   [--all|-a]   [--extend|-e]   [--verbose|-v]   [--program|-p]  [--numeric|-n]
			# netstat -i
				显示所有接口
			# netstat -I<IFACE>
				显示指定接口
				选项与接口之间没有空格

ss

ss
	another utility to investigate sockets
	格式:ss [OPTION]... [FILTER]

	-t		TCP协议相关
	-u		UDP协议相关
	-w		裸套接字(raw socket)相关
	-x		unix sock相关
	-a		相关协议的所有连接
	-l		监听(listen)状态的套接字
	-e		显示扩展信息
	-m		显示套接字连接所使用的内存信息
	-p		显示进程及PID
	-n		以数字格式显示地址及端口
	-o		计时器信息
	
	TCP的常见状态
		TCP Finite State Machine:TCP有限状态机
			LISTEN
			ESTABLISHED
			FIN_WAIT_1
			FIN_WAIT_2
			SYN_SENT
			SYN_RECV
			CLOSED
			…
			
		EXPRESSION:
			dport = 
			sport = 
			示例:’( dport = :ssh or sport = :ssh )’
			
		常用组合:
			-tan,-tanl,-tanlp,-uan
			
	USAGE EXAMPLES
	       ss -t -a
	              Display all TCP sockets.
	
	       ss -u -a
	              Display all UDP sockets.
	
	       ss -o state established '( dport = :ssh or sport = :ssh )'
	              Display all established ssh connections.
	
	       ss -x src /tmp/.X11-unix/*
	              Find all local processes connected to X server.
	
	       ss -o state fin-wait-1 '( sport = :http or sport = :https )' dst 193.233.7/24
	              List all the tcp sockets in state FIN-WAIT-1 for our apache to network 193.233.7/24 and look at their timers.

ethtool

ethtool
	query or control network driver and hardware settings
	查询或控制网络驱动程序和硬件设置

	ethtool [OPTIONS] DEVICE

	-S						显示统计数据
	autoneg {on|off}		是否开启自动协商功能

tcpdump

该工具是一个网络抓包分析工具,支持将信息保存到文件,其用法为

tcpdump [OPTION]
	OPTION
		-a							尝试将网络和广播地址转换成名称;
		-c<数据包数目>				收到指定的数据包数目后,就停止进行倾倒操作;
		-d							把编译过的数据包编码转换成可阅读的格式,并倾倒到标准输出;
		-dd							把编译过的数据包编码转换成C语言的格式,并倾倒到标准输出;
		-ddd						把编译过的数据包编码转换成十进制数字的格式,并倾倒到标准输出;
		-e							在每列倾倒资料上显示连接层级的文件头;
		-f							用数字显示网际网络地址;
		-F<表达文件>					指定内含表达方式的文件;
		-i<网络接口>					使用指定的网络接口送出数据包;
		-l							使用标准输出列的缓冲区;
		-n							不把主机的网络地址转换成名字;
		-N							不列出域名;
		-O							不将数据包编码最佳化;
		-p							不让网络界面进入混杂模式;
		-q							快速输出,仅列出少数的传输协议信息;
		-r<数据包文件>				从指定的文件读取数据包数据;
		-s<数据包大小>				设置每个数据包的大小;
		-S							用绝对而非相对数值列出TCP关联数;
		-t							在每列倾倒资料上不显示时间戳记;
		-tt							在每列倾倒资料上显示未经格式化的时间戳记;
		-T<数据包类型>				强制将表达方式所指定的数据包转译成设置的数据包类型;
		-v							详细显示指令执行过程;
		-vv							更详细显示指令执行过程;
		-x							用十六进制字码列出数据包资料;
		-w<数据包文件>				把数据包数据写入指定的文件。

[root@localhost ~]# tcpdump -c 10 -i eno16777736
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eno16777736, link-type EN10MB (Ethernet), capture size 65535 bytes
10:27:29.476322 IP 192.168.18.128.ssh > 192.168.18.1.7788: Flags [P.], seq 3952087576:3952087788, ack 3509102863, win 159, length 212
10:27:29.476615 IP 192.168.18.1.7788 > 192.168.18.128.ssh: Flags [.], ack 212, win 514, length 0
10:27:29.476856 IP 192.168.18.128.48623 > 192.168.18.2.domain: 38219+ PTR? 1.18.168.192.in-addr.arpa. (43)
10:27:29.483259 IP 192.168.18.2.domain > 192.168.18.128.48623: 38219 NXDomain 0/0/0 (43)
10:27:29.483581 IP 192.168.18.128.56076 > 192.168.18.2.domain: 61781+ PTR? 128.18.168.192.in-addr.arpa. (45)
10:27:29.527056 IP 192.168.18.2.domain > 192.168.18.128.56076: 61781 NXDomain 0/0/0 (45)
10:27:29.527473 IP 192.168.18.128.60314 > 192.168.18.2.domain: 26697+ PTR? 2.18.168.192.in-addr.arpa. (43)
10:27:29.527665 IP 192.168.18.128.ssh > 192.168.18.1.7788: Flags [P.], seq 212:504, ack 1, win 159, length 292
10:27:29.567665 IP 192.168.18.2.domain > 192.168.18.128.60314: 26697 NXDomain 0/0/0 (43)
10:27:29.567991 IP 192.168.18.128.ssh > 192.168.18.1.7788: Flags [P.], seq 504:1276, ack 1, win 159, length 772
10 packets captured
10 packets received by filter
0 packets dropped by kernel

三、Linux进程管理模型

1. 进程管理基础

Linux内核

内核的任务

  • 就计算机整体而言,内核(Kernel)是硬件与软件之间的一个中间层,其作用就是将应用程序的请求传递给硬件,并充当底层驱动程序,对系统中的各种设备个组件进行寻址

Kernel_1

  • 从程序的角度来看,内核可以被认为是一台增强的计算机,将计算机抽象到一个高层次上。应用程序只需发出指令,实际如何完成与应用程序是无关的,内核抽象了实现细节

  • 当多个程序在同一系统中并发运行时,也可以将内核视为资源管理与调度程序,内核负责将可用的共享资源(如CPU时间、磁盘空间、网络资源等)分配到各个系统进程,同时需要保证系统的完整性

  • 也可以将内核视为,他提供了一组面向系统的命令。如下图,这里的库为Libraries,通常以API(Application Programming Interface,应用编程接口)的形式提供,是软件系统不同组成部分衔接的约定;此外,还有更底层的ABI(Application Binary Interface,应用二进制接口),定义了机器代码如何访问数据结构与运算程序,此处所定义的界面相当低级并且相依于硬件

system_call

内核的实现

在操作系统的实现方面,目前有两种主要类型

  • 微内核(Micro kernel)是将各种服务功能放到内核之外,自身仅仅是一个消息中转战,用于各种功能间的通讯
  • 宏内核(Monolithic kernel),也称作单内核,是将所有服务功能集成于一身,使用时直接调用

目前,Linux使用宏内核的设计规范,同时也借鉴了微内核的设计思想,通过模块,使得可以向内核动态添加或卸载功能,弥补了宏内核的一些缺陷

Kernel_design

进程的调度

由于Linux是多任务系统,它支持并发执行的若干进程(用户看来如此),而系统中真正同时运行的进程数目最多不能超过CPU数目,因此内核会按照d短的时间间隔在不同的进程之间切换,如此就造成了同时处理多进程的假象

内核借助于CPU,负责进程切换的技术细节。通过在撤销进程的CPU资源之前保存进程所有与状态相关的要素,并将进程终于空闲状态;而在重新激活进程时,将保存的状态原样恢复。进程之间的切换称为进程切换

另外,内核还需要确定如何在现存进程之间共享CPU时间,重要的进程得到的CPU多一些,次要的少一些。确定哪个进程运行多长时间的过程称为调度

2. 进程与线程

进程

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础传统上

在类Unix系统下运行的应用程序、服务器以及其他程序都成为进程,每个进程都在CPU的虚拟内存(Virtual Memory)中分配地址空间,各进程的地址空间是完全独立的

进程是由PID(Process IDentification进程标识符)表示的。从用户的角度来看,一个 PID 是一个数字值,可惟一标识一个进程。一个 PID 在进程的整个生命期间不会更改,但 PID 可以在进程销毁后被重新使用

Linux进程采用了一种层次系统每个进程依赖于一个父进程,内核启动init程序(如今已被systemd取代,以下统称为init程序)作为第一个进程,因此该程序为进程树的根,所有的进程都直接或间接起源自该进程。如下为使用pstree查看进程树的结果

[root@localhost ~]# pstree
systemd─┬─ModemManager───2*[{ModemManager}]
        ├─NetworkManager─┬─dhclient
        │                └─3*[{NetworkManager}]
        ├─2*[abrt-watch-log]
        ├─abrtd
        ├─agetty
        ├─alsactl
        ├─atd
        ├─auditd─┬─audispd─┬─sedispatch
        │        │         └─{audispd}
        │        └─{auditd}
        ├─bluetoothd
        ├─chronyd
        ├─crond
        ├─dbus-daemon───{dbus-daemon}
        ├─dmeventd───2*[{dmeventd}]
        ├─irqbalance
        ├─lsmd
        ├─lvmetad───{lvmetad}
        ├─master─┬─pickup
        │        └─qmgr
        ├─polkitd───5*[{polkitd}]
        ├─rngd
        ├─rsyslogd───2*[{rsyslogd}]
        ├─smartd
        ├─sshd─┬─sshd───bash
        │      ├─sshd───bash───man───less
        │      └─sshd───bash───pstree
        ├─systemd-journal
        ├─systemd-logind
        ├─systemd-udevd
        ├─tuned───4*[{tuned}]
        └─vmtoolsd───{vmtoolsd}

该树形结构的扩展方式与新进程的创建方式密切相关,Linux有两种创建新进程的机制,forkexec

  • fork可创建当前进程的一个副本,父进程只有PID与子进程不同,在该系统调用(即fork)执行之后,系统中有两个进程,都执行同样的操作

    • 另外,Linux使用一种称为CoW(Copy on Write,写时复制)的技术来时fork更为高效。其原理是将内存复制操作延迟到父进程子进程向某内存页面写入数据,之前,在只读访问的情况下父进程与子进程可以共用同一内存页
  • exec将一个新程序加载到当前进程的内存中并执行,旧程序的内存页将刷出,其内容将替换为新的数据,而后开始执行新程序

进程的表示:task_struct

Linux内核涉及进程和程序的所有算法都围绕数据结构task_struct建立,该结构定义在include/sched.h中。task_struct包含很多成员,将进程与各内核子系统联系起来

task_struct

task_struct定义的部分内容如下:

struct task_struct {
    volatile long state; /* -1表示不可运行,0表示可运行,>0表示停止 */
    void *stack;
    atomic_t usage;
    unsigned long flags; /* 每进程标志,下文定义 */
    unsigned long ptrace;
    int lock_depth; /* 大内核锁深度 */
    int prio, static_prio, normal_prio;
    struct list_head run_list;
    const struct sched_class *sched_class;
    struct sched_entity se;
    unsigned short ioprio;
    unsigned long policy;
    cpumask_t cpus_allowed;
    unsigned int time_slice;
#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
    struct sched_info sched_info;
#endif
    struct list_head tasks;
/*
* ptrace_list/ptrace_children链表是ptrace能够看到的当前进程的子进程列表。
*/
    struct list_head ptrace_children;
    struct list_head ptrace_list;
    struct mm_struct *mm, *active_mm;
/* 进程状态 */
    struct linux_binfmt *binfmt;
    long exit_state;
    int exit_code, exit_signal;
    int pdeath_signal; /* 在父进程终止时发送的信号 */
    unsigned int personality;
    unsigned did_exec:1;
    pid_t pid;
    pid_t tgid;
/*
* 分别是指向(原)父进程、最年轻的子进程、年幼的兄弟进程、年长的兄弟进程的指
*(p->father可以替换为p->parent->pid)
*/
    struct task_struct *real_parent; /* 真正的父进程(在被调试的情况下) */
    struct task_struct *parent; /* 父进程 */
/*
* children/sibling链表外加当前调试的进程,构成了当前进程的所有子进程
*/
    struct list_head children; /* 子进程链表 */
    struct list_head sibling; /* 连接到父进程的子进程链表 */
    struct task_struct *group_leader; /* 线程组组长 */
/* PID与PID散列表的联系。 */
    struct pid_link pids[PIDTYPE_MAX];
    struct list_head thread_group;
    struct completion *vfork_done; /* 用于vfork() */
    int __user *set_child_tid; /* CLONE_CHILD_SETTID */
    int __user *clear_child_tid; /* CLONE_CHILD_CLEARTID */
    unsigned long rt_priority;
    cputime_t utime, stime, utimescaled, stimescaled;
    unsigned long nvcsw, nivcsw; /* 上下文切换计数 */
    struct timespec start_time; /* 单调时间 */
    struct timespec real_start_time; /* 启动以来的时间 */
/* 内存管理器失效和页交换信息,这个有一点争论。它既可以看作是特定于内存管理器
也可以看作是特定于线程的 */
    unsigned long min_flt, maj_flt;
    cputime_t it_prof_expires, it_virt_expires;
    unsigned long long it_sched_expires;
    struct list_head cpu_timers[3];
/* 进程身份凭据 */
    uid_t uid,euid,suid,fsuid;
    gid_t gid,egid,sgid,fsgid;
    struct group_info *group_info;
    kernel_cap_t cap_effective, cap_inheritable, cap_permitted;
    unsigned keep_capabilities:1;
    struct user_struct *user;
    char comm[TASK_COMM_LEN]; /* 除去路径后的可执行文件名称-用et_task_comm访(其中用task_lock()锁定它)-通常由flush_old_exec初始化 */
/* 文件系统信息 */
    int link_count, total_link_count;
/* ipc相关 */
    struct sysv_sem sysvsem;
/* 当前进程特定于CPU的状态信息 */
    struct thread_struct thread;
/* 文件系统信息 */
    struct fs_struct *fs;
/* 打开文件信息 */
    struct files_struct *files;
/* 命名空间 */
    struct nsproxy *nsproxy;
/* 信号处理程序 */
    struct signal_struct *signal;
    struct sighand_struct *sighand;
    sigset_t blocked, real_blocked;
    sigset_t saved_sigmask; /* 用TIF_RESTORE_SIGMASK恢复 */
    struct sigpending pending;
    unsigned long sas_ss_sp;
    size_t sas_ss_size;
    int (*notifier)(void *priv);
    void *notifier_data;
    sigset_t *notifier_mask;
#ifdef CONFIG_SECURITY
    void *security;
#endif
/* 线程组跟踪 */
    u32 parent_exec_id;
    u32 self_exec_id;
/* 日志文件系统信息 */
    void *journal_info;
/* 虚拟内存状态 */
    struct reclaim_state *reclaim_state;
    struct backing_dev_info *backing_dev_info;
    struct io_context *io_context;
    unsigned long ptrace_message;
    siginfo_t *last_siginfo; /* 由ptrace使用。*/
...
};

task_struct结构体的内容可以分解为各个部分,每个部分表示进程的一个方面

  • 状态和执行信息,如PID,到父进程及其他有关进程的指针,优先级等

  • 有关已经分配的虚拟内存信息

  • 进程身份凭据,如用ID、组ID以及权限等

  • 使用的文件信息

  • 线程信息记录该进程特定于CPU的运行时间数据(与硬件无关)

  • 与其他应用程序协作时所需的进程间通信相关信息

  • 该进程所用的信号处理程序,用于响应信号的到来

此外,tasks字段提供了链接列表的能力。它包含一个 prev 指针(指向前一个任务)和一个 next 指针(指向下一个任务)

进程的优先级

并非所有的进程具有相同的重要性,如下图,进程运行按照时间片(Time Slice)调度,分配给进程的时间片份额与其重要性相关

Time_slice

这种方式成为抢占式多任务(Preemptive Multitasking),各个进程都分配到一定的时间段可以执行,时间到期后,内核会从进程收回控制权,让另一个进程运行

被抢占的进程的运行时环境,即所有CPU寄存器的内容与页表,都会被保存,因此其运行结果不会丢失,在该进程恢复执行时,其环境可完全恢复

但是,若进程在某时刻可能因为无事可做而浪费CPU时间,这显然是不合理的,因此,当调度器在进程间切换时,需要指定每个进程的状态

进程的生命周期

进程可能有以下状态

Process_status

  • 已创建(Created):进程第一次创建时,即为已创建(或新建(New))状态,此状态下的进程将等待进入就绪状态,而在大部分操作系统中,这将是自动的

  • 等待/就绪(Waiting/Ready):进程能够运行,但没有获得许可,因为CPU分配给了另一个进程,调度器可以在下一次任务切换时选择该进程

  • 运行(Running):程序正在运行

  • 阻塞(Blocked):进程在等待一个外部事件,该事件完成前进程无法继续

  • 终止(Terminated):当进程运行完成自己的任务,或显式被杀死时,将进入终止状态

  • 其他状态
    • Swapped out and waiting,也称为suspended and waiting,进程在外存中,但是只要被载入内存就可以执行
    • Swapped out and blocked,也称为suspended and blocked,进程在外存中并等待一个事件
    这两种状态中,进程都“存储”在辅助存储器(通常是硬盘)上
僵尸进程

此外还有一种状态需要说明,即僵尸进程(Zombie Process),顾名思义,这样的进程进程已经死亡,但仍然以某种方式活着!即他们占用的资源(内存,占用的设备等)已经释放,而进程表中仍然有对应的表项

而僵尸进程产生的原因,在于Unix-Like操作系统下进程创建与销毁的方式。在以下两种事件发生时,进程将终止运行

    1. 程序必须由另一个进程或用户杀死,通常是通过SIGTERMSIGKILL信号完成,这是正常的终止进程
    1. 进程的父进程在子进程终止时必须调用或已经调用wait4(wait for之意)系统调用,这相当于向内核证实父进程已经确认子进程的终结,该系统调用是的内核可以释放为子进程保留的资源

而在第一个事件发生且第二个事件未发生时,就会出现“僵尸”进程,如图

Zombie_Process

在进程终止之后,其数据尚未从进程表删除前,进程就处于“僵死”态,如父进程没有发出wait调用,僵尸进程可能一直存在

孤儿进程

当一个父进程由于正常完成工作而退出或由于其他情况被终止,它的一个或多个子进程却还在运行,那么那些子进程将成为孤儿进程。为避免孤儿进程退出时无法释放所占用的资源而僵死,进程号为1的init进程将会接受这些孤儿进程,这一过程也被称为“收养”(re-parenting)

线程

进程并不是内核支持的唯一一种执行形式,除了重量级进程(也称为Unix进程)之外,还有一种形式,即线程(Thread)(有时也称为轻量级进程

一般,一个进程可能由若干线程组成,这些线程共享同样的数据和资源,但可能执行程序中不同的代码。如今,线程概念已经集成到编程语言中,同时,在软件开发中,也有一些并行编程模型,如多进程、单进程多线程等

可以理解为,进程是一个正在执行的程序,而线程则是与主程序并行运行的程序函数或例程。由于线程和主程序共享同样的地址空间,主程序自动就可以访问接收到的数据,因此除了为防止线程访问同一内存区而采取的互斥机制外,就不需要什么通信了

3. 资源管理

从资源管理与分配角度来讲,Linux内核负责将底层应将的计算能力抽象化为系统调用,对上层提供,此处介绍CPU与内存资源的分配

地址空间

由于内存区域是通过指针寻址,因此CPU的字长决定了所能管理的地址空间的最大长度。对于32位系统(如IA-32、PPC、m68k),其最大寻址能力为232=4GB;而对于64位系统(Alpha、IA-64、AMD64),则为264B

地址空间的最大长度与实际可用的物理内存数量无关,由此,也被称作虚拟地址空间。从系统中每个进程的角度来看,地址空间中只有自身一个进程,而无法感知到其他进程的存在

Linux将虚拟地址空间划分为两部分,即内核空间(Kernel Space)与用户空间(User Space)
Virtual_memory

系统中每个用户进程都有吱声的虚拟地址范围,从0到TASK_SIZE;而用户空间之上的区域(即TASK_SIZE到232或264)保留给内核使用,用户进程不得访问

TASK_SIZE是一个特定于计算机体系结构的常数,吧地址空阿金按照给定的比例划分为两部分。例如在IA-32系统中,系统空间在3GB处划分,因此每个进程的虚拟地址空间是3GB,内核就有1GB可用(虚拟地址空间的总长度为4GB)。以下以该架构为例说明

再次说明,这种划分的可用内存数与实际内存无关,由于地址空间虚拟化的结果,每个用户进程都认为自身有3GB的内存,而虚拟地址空间顶部的内核空间总是同样的,无论当前执行的是哪个进程

特权级别

内核将虚拟地址空间划分为两个部分,因此能够保护各个同进程,使之彼此隔离。所有的现代CPU都提供了几种特权级别,进程可以驻留在某一特权级别

每个特权级别都有各种限制,例如对执行某些汇编语言指令或访问虚拟地址空间某一特定部分的限制

IA-32体系结构使用4种特权级别,即保护环(Protection Rings),内环可以访问更多的功能,如图

CPU_Ring
而Linux值使用两种不同的状态:内核态与用户态。两种状态的关键差别在对于改与TASK_SIZE的内存区域的访问,即在用户状态进制访问内核空间,用户进程不能操作或读取内核空间中的数据,也无法执行内核空间中的代码。该机制可防止进程无意间修改彼此的数据而造成的相互干扰

若普通进程想要执行任何影响整个系统的操作(如操作I/O),则只能借助于系统调用想内核发出请求。内核检查进程是否允许执行想要的操作,而后代表进程执行所需的操作,返回到用户状态

CPU大多数时间都在执行用户空间中的代码,当应用程序执行系统调用时,切换到核心态,内核将完成其请求,在此期间,内核可以访问虚拟地址空间中的用户部分,在系统调用完成后,CPU切换会用户状态,硬件中断也会使CPU切换到核心态,这种情况下内核不能访问用户空间

在用户态与核心态执行

地址映射

由于每个进程都有自身的虚拟地址空间,因此内核必须考虑如何将实际可用的物理内存映射到虚拟地址空间的区域,这种物理地址与逻辑地址的映射关系保存在一种叫页表(Page Table)

在该映射中,每个映射被称为PTE(Page Table Entry,分页表项),虚拟地址关系到进程的用户空间和内核空间,而物理地址则用来寻址实际可用的内存,如图

Page_Table

如图,虚拟空间内内核划分为很多等长的部分,称之为,同样,物理内存页被划分为多个页,不过物理内存页一般为称为页帧(Page Frame)

页表

实现两个地址空间的关联最容易的方式是使用数组,对虚拟内存空间的每一页,都分配一个数组项

而因为虚拟地址空间的大部分区域都没有使用,因而也没有关联到页帧,那么久可以使用多级分页

多级分页

如图,计算机体系结构设计会将虚拟地址划分为多个部分,具体在何处划分依据不同的体系结构而已

Linux操作了四级页表,第一分部为PGD(Page Global Directory,全局页目录),用于索引进程中的一个数组(每个进程有且仅有一个),该数组即PGD,他指向另一些数组的起始地址,这些地址就是PUD(Page Upper Directory,上级页目录)

以此类推,PUD指向PMD(Page Middle Directory,中间页目录),PMD的数组项也是指针,指向下一级数据,称为页表页目录,即第四部分PTE(Page Table Entry)

至此,虚拟内存页与页帧之间的映射就此完成,页表的数组项是直接指向页帧的

最后一部分为偏移量,他指定了页内部一个字节的位置,归根结底,每个地址都指向地址空间中唯一定义的某个字节

另外,CPU还提供一下两种机制来加速内存访问

  • CPU中有一个专门的部件,称为MMU(Memory Management Unit,内存管理单元),优化了内存访问
  • 对于地址转换中频繁出现的地址,保存到TLB(Translation Lookaside Buffer,地址转换后备缓冲)高速缓存,从而无需在访问内存中的页表就可从高速缓存中直接获得地址数据

物理内存的分配

Buddy

在内核分配内存时,必须记录页帧的已分配或空闲状态,以避免两个进程使用相同的内存区域,另外,还需要保证该操作尽快完成

内核中很多是要要求分配连续页,为了快速检测内存中的连续区域,内核采用了一种叫做伙伴系统(Buddy System)的机制

系统中的空闲内存块总是两两分组,每组中的两个内存块称为伙伴(Buddy ),伙伴的分配可以是彼此独立的,但若两个伙伴都是空闲的,内核会将其合并为一个更大的内存块,作为下一层的某个内存块的伙伴

Buddy System

内核对所有大小相同的伙伴(1、2、4、8、16……)都放在同一个列表中管理

若系统需要8个页帧,则将16个页帧组成的块拆分为两个伙伴,其中一个块用来满足应用程序的请求,而剩余的8个页帧则放置到对应8页块大小内存块列表中

在应用释放内存时,内核可以直接检查地址,来判断能否创建一组伙伴,并合并为一个更大的内存块放回到伙伴列表中

slab

内核本身经常需要比完整页帧小很多的内存块,由于内核无法使用标准库的函数,因而必须在伙伴系统的基础上自行定义额外的内存管理层,将伙伴系统划分为更小的部分

该方法不仅可以分配内存,还为频繁使用的小对象实现了一个一般性的缓存,即slab缓存,他使用两种方法分配内存

  • 对频繁使用的对象,内核定义了只包含了所需类型对象实例的缓存,每次需要某种对象时,可以从对象的缓存快速分配,使用后释放到缓存。slab缓存自动维护与伙伴系统的交互,在缓存用尽时请求新的页帧

  • 对通常情况下小内存块的分配,内核针对不同大小的对象定义了一组slab缓存,可以像用户空间编程一样,用相同的函数访问这些缓存。但是这些函数名都增加了前缀“k”,以表示是与内核相关联:kmalloc,kfree

slab与Buddy分配机制的关系如下图

slab

页面交换

页面交换通过利用磁盘空间作为扩展内存,从而增大了可用内存3

在内核需要更多内存时,不经常使用页可以写入磁盘,即LRU(Least Recently Used)机制。若再需要访问相关数据,内核会将相应的页切换会内存

通过缺页异常机制,这种切换操作对于程序而言是透明的。而页面回收用户将内存映射被修改的内存与底层的块设备同步,因此有时也被称为数据回写。数据刷出后,内核即可将页帧用于其他用途(类似于页面交换)

swap

在Unix-Like操作系统中,使用Swap来描述在RAM和磁盘之间移动内存页面的行为,同时也使用Swap来表示存储页面的区域

若将磁盘的某个分区用于交换,则该分区叫做Swap分区(Swap Partitions),而专用于交换的硬盘称为交换驱动器(Swap Drive)、Scratch DriveScratch Disk

而由于磁盘与RAM的速度差了几个数量级,加之使用机械存储设备会为硬盘带来几毫秒的延迟,因此,在实际可行的情况下,希望减少或消除交换

Linux提供了参数,该参数更改了交换运行时内存之间的平衡,而不是从系统页面缓存中删除页面:/proc/sys/vm/swappiness

许多类Unix操作系统(例如AIX,Linux和Solaris)允许并行使用多个存储设备用于交换空间,以提高性能

四、进程管理命令

在介绍命令之前,再对上面的介绍作以补充

1. Linux进程

上文已有介绍,进程都是动态创建并由一个动态分配的 task_struct 表示。一个例外是 init 进程本身,它总是存在并由一个静态分配的 task_struct 表示,以下为 ./linux/arch/ia64/kernel/init_task.c 部分内容

static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
/*
 * Initial task structure.
 *
 * We need to make sure that this is properly aligned due to the way process stacks are
 * handled. This is done by having a special ".data..init_task" section...
 */
#define init_thread_info	init_task_mem.s.thread_info

union {
	struct {
		struct task_struct task;
		struct thread_info thread_info;
	} s;
	unsigned long stack[KERNEL_STACK_SIZE/sizeof (unsigned long)];
} init_task_mem asm ("init_task") __init_task_data =
	{{
	.task =		INIT_TASK(init_task_mem.s.task),
	.thread_info =	INIT_THREAD_INFO(init_task_mem.s.task)
}};

EXPORT_SYMBOL(init_task);

proc FS

进程数据文件系统(process data filesystem),即procfs,proc FS就此得名,通常装载在/proc

proc文件系统是一种伪文件系统,其信息不能从块设备获取,只有在读取文件内容时,才动态生成相关信息。可以获得有关内核各子系统的信息(如,内存使用率,附接的外设等),也可在不重新表一内核源码的情况下修改内核的行为,或重启系统

proc文件系统提供了一种接口,可用于sysctl(system control mechanism)机制导出的选项,都可以修改

每一个进程都有其PID,在支持伪文件系统的发行版中,/proc/目录下存放有以该进程PID命名的目录(init的PID为1),该目录将进程运行的相关信息以文件的形式显示

[root@localhost ~]# ls /proc/8184
attr       clear_refs       cpuset   fd       limits    mountinfo   ns         oom_score_adj  root       stack   syscall
autogroup  cmdline          cwd      fdinfo   loginuid  mounts      numa_maps  pagemap        sched      stat    task
auxv       comm             environ  gid_map  maps      mountstats  oom_adj    personality    sessionid  statm   uid_map
cgroup     coredump_filter  exe      io       mem       net         oom_score  projid_map     smaps      status  wchan

主要内容如下

内容意义
/proc/PID/cmdline启动该进程的命令行
/proc/PID/cwd当前工作目录的符号链接
/proc/PID/environ影响进程的环境变量的名字和值
/proc/PID/exe最初的可执行文件的符号链接, 如果它还存在的话
/proc/PID/fd一个目录,包含每个打开的文件描述符的符号链接
/proc/PID/fdinfo一个目录,包含每个打开的文件描述符的位置和标记
/proc/PID/maps一个文本文件包含内存映射文件与块的信息
/proc/PID/mem一个二进制图像(image)表示进程的虚拟内存, 只能通过ptrace化进程访问
/proc/PID/root该进程所能看到的根路径的符号链接。如果没有chroot监狱(由chroot创造出的那个根目录),那么进程的根路径是/
/proc/PID/status包含了进程的基本信息,包括运行状态、内存使用
/proc/PID/task一个目录包含了硬链接到该进程启动的任何任务

进程关系

Unix-like系统的进程创建模型我们称之为“家族关系”,不过该家族中没有其他亲戚,只有父母这一脉?,即

  • 若进程A分支形成进程B,则进程A就是父进程(Parent Process),进程B为子进程(Child Process)

  • 若进程B再次分支建立一个进程C,则进程与进程C之间可以称为祖孙关系

  • 若进程A分支再次形成几个子进程B1、B2,则B1、B2之间称为兄弟关系

在上文中,列出了task_struct部分定义,其中有两个链表表头实现了这种关系

struct task_struct {
/*
* children/sibling链表外加当前调试的进程,构成了当前进程的所有子进程
*/
    struct list_head children; /* 子进程链表 */
    struct list_head sibling; /* 连接到父进程的子进程链表 */
...
};

进程类型

在Linux系统中,进程主要由三种类型

  • 交互进程
    由一个Shell启动的进程
    交互进程既可以在前台运行,也可以在后台运行
  • 批处理进程
    不与特定的终端相关联,提交到等待队列种顺序执行的进程
  • 守护进程
    在Linux在启动时初始化,需要时运行于后台的进程

2. IPC

IPC(Inter-Process Communication,进程间通信),指至少两个进程或线程间传送数据或信号的一些技术或方法

关于进程间通信的方式,本主题涉及到的主要为:

  • shm:shared memory
  • Signal:信号
  • Semaphore:旗语

此处顺表一提,不同主机上的进程通信,一般可通过RPC(Remote Procedure Call,远程过程调用)或Socket进行

Linux系统上的常用信号,在Bash编程-信号捕捉中已有介绍,此处再次列出:

信号描述
1SIGHUP挂起进程,让一个进程不必重启即可重读其配置文件
2SIGINT中断进程,Ctrl+C
9SIGKILL杀死进程
15SIGTERM终止一个进程
18SIGCONT调回后台进程
19SIGSTOP停止一个进程,即送往后台,Ctrl+Z

可通过SIGNAL(7)查看更多信息

3. 进程管理命令

ps

ps可理解为Process State或Process Snapshot,用于显示系统进程在执行该命令时的状态,默认只显示当前终端上的进程

[root@localhost ~]# ps
   PID TTY          TIME CMD
  8064 pts/1    00:00:00 bash
  8412 pts/1    00:00:00 ps

该命令的使用格式较为简单:ps [OPTIONS]

ps命令的选项有三种风格

  • Unix风格:选项需要加-
  • BSD风格:选项不能加-
  • GNU长选项风格:使用--
BSD风格
	常用组合:aux
		a:显示所有与终端有关的进程
		u:以用户为中心组织进程状态显示
		x:显示所有与终端无关的进程(未必都是无关)

以下为部分输出

[root@localhost ~]# ps aux
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          1  0.0  0.3  44016  6496 ?        Ss   08:16   0:05 /usr/lib/systemd/systemd --switched-root --system --deseriali
root          2  0.0  0.0      0     0 ?        S    08:16   0:00 [kthreadd]
root          3  0.0  0.0      0     0 ?        S    08:16   0:00 [ksoftirqd/0]
root          5  0.0  0.0      0     0 ?        S<   08:16   0:00 [kworker/0:0H]
root          6  0.0  0.0      0     0 ?        S    08:16   0:00 [kworker/u256:0]
root          7  0.0  0.0      0     0 ?        S    08:16   0:00 [migration/0]
root          8  0.0  0.0      0     0 ?        S    08:16   0:00 [rcu_bh]
root          9  0.0  0.0      0     0 ?        S    08:16   0:00 [rcuob/0]
root        137  0.0  0.0      0     0 ?        S    08:16   0:05 [rcu_sched]
root        138  0.0  0.0      0     0 ?        S    08:16   0:02 [rcuos/0]
root        266  0.0  0.0      0     0 ?        S    08:16   0:00 [watchdog/0]
root        267  0.0  0.0      0     0 ?        S    08:16   0:00 [watchdog/1]
root        268  0.0  0.0      0     0 ?        S    08:16   0:00 [migration/1]
root        269  0.0  0.0      0     0 ?        S    08:16   0:00 [ksoftirqd/1]
root        271  0.0  0.0      0     0 ?        S<   08:16   0:00 [kworker/1:0H]
root        272  0.0  0.0      0     0 ?        S    08:16   0:00 [watchdog/2]
root        273  0.0  0.0      0     0 ?        S    08:16   0:00 [migration/2]
root        274  0.0  0.0      0     0 ?        S    08:16   0:00 [ksoftirqd/2]
root        275  0.0  0.0      0     0 ?        S    08:16   0:01 [kworker/2:0]
root        276  0.0  0.0      0     0 ?        S<   08:16   0:00 [kworker/2:0H]
root        277  0.0  0.0      0     0 ?        S    08:16   0:00 [watchdog/3]
root        278  0.0  0.0      0     0 ?        S    08:16   0:00 [migration/3]
root        279  0.0  0.0      0     0 ?        S    08:16   0:00 [ksoftirqd/3]
root        281  0.0  0.0      0     0 ?        S<   08:16   0:00 [kworker/3:0H]
root        282  0.0  0.0      0     0 ?        S<   08:16   0:00 [khelper]
root        283  0.0  0.0      0     0 ?        S    08:16   0:00 [kdevtmpfs]
root        284  0.0  0.0      0     0 ?        S<   08:16   0:00 [netns]
root        285  0.0  0.0      0     0 ?        S<   08:16   0:00 [writeback]
root        286  0.0  0.0      0     0 ?        S<   08:16   0:00 [kintegrityd]
root        287  0.0  0.0      0     0 ?        S<   08:16   0:00 [bioset]
root        288  0.0  0.0      0     0 ?        S<   08:16   0:00 [kblockd]
root        289  0.0  0.0      0     0 ?        S    08:16   0:00 [khubd]
root        290  0.0  0.0      0     0 ?        S<   08:16   0:00 [md]
root        293  0.0  0.0      0     0 ?        S    08:16   0:00 [khungtaskd]
root        294  0.0  0.0      0     0 ?        S    08:16   0:00 [kswapd0]
root        295  0.0  0.0      0     0 ?        SN   08:16   0:00 [ksmd]
root        296  0.0  0.0      0     0 ?        SN   08:16   0:00 [khugepaged]
root        297  0.0  0.0      0     0 ?        S    08:16   0:00 [fsnotify_mark]
root        298  0.0  0.0      0     0 ?        S<   08:16   0:00 [crypto]
root        307  0.0  0.0      0     0 ?        S<   08:16   0:00 [kthrotld]
root        309  0.0  0.0      0     0 ?        S    08:16   0:00 [kworker/u256:1]
root        310  0.0  0.0      0     0 ?        S<   08:16   0:00 [kmpath_rdacd]
root        311  0.0  0.0      0     0 ?        S<   08:16   0:00 [kpsmoused]
root        331  0.0  0.0      0     0 ?        S<   08:16   0:00 [deferwq]
root        332  0.1  0.0      0     0 ?        R    08:16   0:13 [kworker/0:1]
root        365  0.0  0.0      0     0 ?        S    08:16   0:00 [kauditd]
root        925  0.0  0.0      0     0 ?        S<   08:16   0:00 [ata_sff]
root        948  0.0  0.0      0     0 ?        S    08:16   0:00 [scsi_eh_0]
root        952  0.0  0.0      0     0 ?        S<   08:16   0:00 [scsi_tmf_0]
root        964  0.0  0.0      0     0 ?        S    08:16   0:00 [scsi_eh_1]
root        970  0.0  0.0      0     0 ?        S<   08:16   0:00 [scsi_tmf_1]
root        989  0.0  0.0      0     0 ?        S<   08:16   0:00 [mpt_poll_0]
root        996  0.0  0.0      0     0 ?        S<   08:16   0:00 [mpt/0]
root       1100  0.0  0.0      0     0 ?        S    08:16   0:00 [scsi_eh_2]
root       1101  0.0  0.0      0     0 ?        S<   08:16   0:00 [scsi_tmf_2]
root       1163  0.0  0.0      0     0 ?        S<   08:16   0:00 [ttm_swap]
root       2857  0.0  0.0      0     0 ?        S<   08:17   0:00 [kworker/3:1H]
root       2868  0.0  0.0      0     0 ?        S    08:17   0:00 [kworker/3:2]
root       3107  0.0  0.0      0     0 ?        S<   08:17   0:00 [kdmflush]
root       3111  0.0  0.0      0     0 ?        S<   08:17   0:00 [bioset]
root       3123  0.0  0.0      0     0 ?        S<   08:17   0:00 [kdmflush]
root       3125  0.0  0.0      0     0 ?        S<   08:17   0:00 [bioset]
root       3155  0.0  0.0      0     0 ?        S<   08:17   0:00 [xfsalloc]
root       3158  0.0  0.0      0     0 ?        S<   08:17   0:00 [xfs_mru_cache]
root       3160  0.0  0.0      0     0 ?        S<   08:17   0:00 [xfs-buf/dm-0]
root       3161  0.0  0.0      0     0 ?        S<   08:17   0:00 [xfs-data/dm-0]
root       3162  0.0  0.0      0     0 ?        S<   08:17   0:00 [xfs-conv/dm-0]
root       3163  0.0  0.0      0     0 ?        S<   08:17   0:00 [xfs-cil/dm-0]
root       3164  0.0  0.0      0     0 ?        S<   08:17   0:00 [kworker/0:1H]
root       3165  0.0  0.0      0     0 ?        S    08:17   0:01 [xfsaild/dm-0]
root       3214  0.0  0.0      0     0 ?        S<   08:17   0:00 [kworker/2:1H]
root       3249  0.0  0.1  39128  3544 ?        Ss   08:17   0:00 /usr/lib/systemd/systemd-journald
root       3273  0.0  0.2 495500  4304 ?        Ssl  08:17   0:00 /usr/sbin/lvmetad -f
root       3274  0.0  0.0      0     0 ?        S<   08:17   0:00 [kworker/1:1H]
root       3288  0.0  0.3  47212  5888 ?        Ss   08:17   0:02 /usr/lib/systemd/systemd-udevd
root       5168  0.0  0.0      0     0 ?        S<   08:17   0:00 [hci0]
root       5171  0.0  0.0      0     0 ?        S<   08:17   0:00 [hci0]
root       5176  0.0  0.0      0     0 ?        S<   08:17   0:00 [bioset]
root       5178  0.0  0.0      0     0 ?        S<   08:17   0:00 [kworker/u257:1]
root       5330  0.0  0.0      0     0 ?        S<   08:17   0:00 [xfs-buf/sda1]
root       5332  0.0  0.0      0     0 ?        S<   08:17   0:00 [xfs-data/sda1]
root       5339  0.0  0.0      0     0 ?        S<   08:17   0:00 [raid5wq]
root       5340  0.0  0.0      0     0 ?        S<   08:17   0:00 [xfs-conv/sda1]
root       5344  0.0  0.0      0     0 ?        S<   08:17   0:00 [dm_bufio_cache]
root       5349  0.0  0.0      0     0 ?        S<   08:17   0:00 [xfs-cil/sda1]
root       5353  0.0  0.0      0     0 ?        S    08:17   0:00 [xfsaild/sda1]
root       5360  0.0  0.0      0     0 ?        S<   08:17   0:00 [kdmflush]
root       5371  0.0  0.0      0     0 ?        S<   08:17   0:00 [bioset]
root       5377  0.0  0.0      0     0 ?        S<   08:17   0:00 [bioset]
root       5379  0.0  0.0      0     0 ?        S    08:17   0:00 [md0_raid5]
root       5388  0.0  0.0      0     0 ?        S<   08:17   0:00 [kdmflush]
root       5389  0.0  0.0      0     0 ?        S<   08:17   0:00 [bioset]
root       5409  0.0  0.0      0     0 ?        S<   08:17   0:00 [kdmflush]
root       5427  0.0  0.0      0     0 ?        S<   08:17   0:00 [bioset]
root       5431  0.0  0.0      0     0 ?        S<   08:17   0:00 [kdmflush]
root       5435  0.0  0.0      0     0 ?        S<   08:17   0:00 [bioset]
root       5436  0.0  0.0      0     0 ?        S<   08:17   0:00 [kdmflush]
root       5440  0.0  0.0      0     0 ?        S<   08:17   0:00 [ksnaphd]
root       5447  0.0  0.0      0     0 ?        S<   08:17   0:00 [kcopyd]
root       5452  0.0  0.0      0     0 ?        S<   08:17   0:00 [bioset]
root       5457  0.0  0.0      0     0 ?        S<   08:17   0:00 [bioset]
root       5468  0.0  0.0      0     0 ?        S<   08:17   0:00 [bioset]
root       5471  0.0  1.2 130088 23556 ?        SLsl 08:17   0:01 /usr/sbin/dmeventd -f
root       6102  0.0  0.0      0     0 ?        S<   08:17   0:00 [xfs-buf/dm-5]
root       6104  0.0  0.0      0     0 ?        S<   08:17   0:00 [xfs-data/dm-5]
root       6105  0.0  0.0      0     0 ?        S<   08:17   0:00 [xfs-conv/dm-5]
root       6106  0.0  0.0      0     0 ?        S<   08:17   0:00 [xfs-cil/dm-5]
root       6107  0.0  0.0      0     0 ?        S    08:17   0:00 [xfsaild/dm-5]
root       6136  0.0  0.0  51148  1600 ?        S<sl 08:17   0:00 /sbin/auditd -n
root       6149  0.0  0.0  80220   848 ?        S<sl 08:17   0:00 /sbin/audispd
root       6150  0.0  0.0  26196   916 ?        S<   08:17   0:00 /usr/sbin/sedispatch
root       6162  0.0  0.0  16752  1380 ?        SNs  08:17   0:00 /usr/sbin/alsactl -s -n 19 -c -E ALSA_CONFIG_PATH=/etc/alsa/a
root       6163  0.0  0.1 130048  2276 ?        Ss   08:17   0:00 /usr/sbin/smartd -n -q never
root       6165  0.0  0.0   4372   596 ?        Ss   08:17   0:00 /sbin/rngd -f
root       6166  0.0  0.1  43916  2500 ?        Ss   08:17   0:00 /usr/sbin/bluetoothd -n
root       6167  0.0  0.4 613940  8836 ?        Ssl  08:17   0:01 /usr/sbin/NetworkManager --no-daemon
libstor+   6168  0.0  0.0   4336   356 ?        Ss   08:17   0:00 /usr/bin/lsmd -d
root       6169  0.0  0.0  28488  1764 ?        Ss   08:17   0:00 /usr/lib/systemd/systemd-logind
root       6170  0.0  0.2 225988  4044 ?        Ssl  08:17   0:00 /usr/sbin/rsyslogd -n
dbus       6171  0.0  0.1  37164  1960 ?        Ssl  08:17   0:00 /bin/dbus-daemon --system --address=systemd: --nofork --nopid
root       6184  0.1  0.2 286244  4448 ?        Ssl  08:17   0:13 /usr/bin/vmtoolsd
root       6186  0.0  1.0 568864 18748 ?        Ssl  08:17   0:03 /usr/bin/python -Es /usr/sbin/tuned -l -P
root       6187  0.0  0.2 225428  5444 ?        Ss   08:17   0:00 /usr/sbin/abrtd -d -s
chrony     6192  0.0  0.0  24728  1532 ?        S    08:17   0:00 /usr/sbin/chronyd -u chrony
root       6195  0.0  0.2 223168  4680 ?        Ss   08:17   0:00 /usr/bin/abrt-watch-log -F BUG: WARNING: at WARNING: CPU: INF
root       6197  0.0  0.2 223168  4676 ?        Ss   08:17   0:00 /usr/bin/abrt-watch-log -F Backtrace /var/log/Xorg.0.log -- /
root       6200  0.0  0.2 347204  5076 ?        Ssl  08:17   0:00 /usr/sbin/ModemManager
root       6208  0.0  0.0  21620  1276 ?        Ss   08:17   0:01 /usr/sbin/irqbalance --foreground
root       6240  0.0  0.0      0     0 ?        S<   08:17   0:00 [krfcommd]
root       6243  0.0  0.0      0     0 ?        S<   08:17   0:00 [kworker/u257:2]
polkitd    6247  0.0  0.6 533592 12060 ?        Ssl  08:17   0:00 /usr/lib/polkit-1/polkitd --no-debug
root       6461  0.0  2.0 136860 37528 ?        S    08:17   0:00 /sbin/dhclient -d -q -sf /usr/libexec/nm-dhcp-helper -pf /var
root       6489  0.0  0.1  82976  3660 ?        Ss   08:17   0:00 /usr/sbin/sshd -D
root       6505  0.0  0.0 126304  1708 ?        Ss   08:17   0:00 /usr/sbin/crond -n
root       6508  0.0  0.0  25932   956 ?        Ss   08:17   0:00 /usr/sbin/atd -f
root       6518  0.0  0.0 110004   828 tty1     Ss+  08:17   0:00 /sbin/agetty --noclear tty1 linux
root       7016  0.0  0.1  93660  2252 ?        Ss   08:17   0:00 /usr/libexec/postfix/master -w
postfix    7036  0.0  0.2  93832  4012 ?        S    08:17   0:00 qmgr -l -t unix -u
root       7807  0.0  0.0      0     0 ?        S    09:00   0:00 [kworker/0:0]
root       7998  0.0  0.0      0     0 ?        S    09:50   0:00 [kworker/2:1]
postfix    8001  0.0  0.2  93764  3988 ?        S    09:57   0:00 pickup -l -t unix -u
root       8002  0.0  0.2 143464  5184 ?        Ss   09:57   0:01 sshd: root@pts/0
root       8006  0.0  0.1 116536  3416 pts/0    Ss   09:57   0:00 -bash
root       8060  0.0  0.2 143464  5184 ?        Ds   09:59   0:00 sshd: root@pts/1
root       8064  0.0  0.1 116536  3448 pts/1    Ss   09:59   0:00 -bash
root       8184  0.7  0.1 122676  2416 pts/0    S+   10:02   0:36 htop
root       8303  0.0  0.0      0     0 ?        R    10:55   0:00 [kworker/1:0]
root       8383  0.0  0.0      0     0 ?        S    11:10   0:00 [kworker/3:0]
root       8444  0.0  0.0      0     0 ?        S    11:22   0:00 [kworker/1:3]
root       8485  0.0  0.0      0     0 ?        S    11:27   0:00 [kworker/1:1]
root       8486  0.0  0.0 141564  1660 pts/1    R+   11:29   0:00 ps aux

输出字段说明:

字段说明
USER进程的属主
PID进程号
%CPU占用CPU的时间百分比
%MEM占用内存的空间百分比
VSZVirtual memory SiZe,虚拟内存集
RSSReSident Size,常驻内存集,不能放到交换内存中
TTY关联到的终端(?表示与终端无关)
STAT进程状态
START启动时间
TIME累计运行时长(占据CPU的时长)
COMMAND哪个命令启动的进程(加[]的表示是内核线程)

此外,关于STAT(进程状态),有以下几个

状态描述
Duninterruptable sleeping(usually IO),不可中断睡眠
Rrunning or runnable(on run queue),运行或就绪
Sinterruptable Sleeping(waiting for an event to complete),可中断睡眠
Tstopped by debugger during the tracing,停止
ZZombie,僵死态
Wpaging (not valid since the 2.6.xx kernel)
Xdead (should never be seen)
tstopped by debugger during the tracing
<high-priority,高优先级进程
Nlow-priority,低优先级进程
+前台进程组中的进程
l多线程进程
sSession leader,会话进程首进程

状态中WXt如今在实际应用中看不到(除了程序员Debug时可能会看到t

Unix风格
	-e:显示所有进程
	-F:显示额外信息
	-f:完整格式列表
	-j:任务格式
	-H:显示进程层次关系
	-l:长格式
	
	-o: 指定要显示的字段
		ps -o PROPERTY1, PROPERTY2
		例:ps -o pid,comm,ni
		常用字段:
			ni:nice值
			priority:优先级
			psr:processor,运行于哪个CPU
			rtprio:real time priority,实时优先级
			pcpu:CPU利用率
			stat:状态
			comm:命令行
			tty:TTY
			ppid:父进程号
			euid:有效用户
			ruid:实际用户
			ppid:父进程

常用选项为-ef-eFH-eo

pmap

pmap意为Process Map,用于报告进程的内存映像信息,使用格式为

pmap [OPTIONS] PID ...

[root@localhost ~]# ps
   PID TTY          TIME CMD
  7673 pts/0    00:00:00 bash
  7817 pts/0    00:00:00 ps
[root@localhost ~]# pmap 7673
7673:   -bash
0000000000400000    884K r-x-- bash
00000000006dc000      4K r---- bash
00000000006dd000     36K rw--- bash
00000000006e6000     24K rw---   [ anon ]
0000000001314000   1448K rw---   [ anon ]
00007ff8d3baf000 103580K r---- locale-archive
00007ff8da0d6000     44K r-x-- libnss_files-2.17.so
00007ff8da0e1000   2044K ----- libnss_files-2.17.so
00007ff8da2e0000      4K r---- libnss_files-2.17.so
00007ff8da2e1000      4K rw--- libnss_files-2.17.so
00007ff8da2e2000   1752K r-x-- libc-2.17.so
00007ff8da498000   2048K ----- libc-2.17.so
00007ff8da698000     16K r---- libc-2.17.so
00007ff8da69c000      8K rw--- libc-2.17.so
00007ff8da69e000     20K rw---   [ anon ]
00007ff8da6a3000     12K r-x-- libdl-2.17.so
00007ff8da6a6000   2044K ----- libdl-2.17.so
00007ff8da8a5000      4K r---- libdl-2.17.so
00007ff8da8a6000      4K rw--- libdl-2.17.so
00007ff8da8a7000    148K r-x-- libtinfo.so.5.9
00007ff8da8cc000   2048K ----- libtinfo.so.5.9
00007ff8daacc000     16K r---- libtinfo.so.5.9
00007ff8daad0000      4K rw--- libtinfo.so.5.9
00007ff8daad1000    132K r-x-- ld-2.17.so
00007ff8dacd6000     12K rw---   [ anon ]
00007ff8dace8000      4K rw---   [ anon ]
00007ff8dace9000     28K r--s- gconv-modules.cache
00007ff8dacf0000      8K rw---   [ anon ]
00007ff8dacf2000      4K r---- ld-2.17.so
00007ff8dacf3000      4K rw--- ld-2.17.so
00007ff8dacf4000      4K rw---   [ anon ]
00007fff03414000    132K rw---   [ stack ]
00007fff0345c000      8K r-x--   [ anon ]
ffffffffff600000      4K r-x--   [ anon ]
 total           116536K

关于选项,我们常用的有-x,显示扩展信息

[root@localhost ~]# pmap 7673 -x
7673:   -bash
Address           Kbytes     RSS   Dirty Mode  Mapping
0000000000400000     884     692       0 r-x-- bash
00000000006dc000       4       4       4 r---- bash
00000000006dd000      36      36      36 rw--- bash
00000000006e6000      24      24      24 rw---   [ anon ]
0000000001314000    1448    1432    1432 rw---   [ anon ]
00007ff8d3baf000  103580      60       0 r---- locale-archive
00007ff8da0d6000      44      20       0 r-x-- libnss_files-2.17.so
00007ff8da0e1000    2044       0       0 ----- libnss_files-2.17.so
00007ff8da2e0000       4       4       4 r---- libnss_files-2.17.so
00007ff8da2e1000       4       4       4 rw--- libnss_files-2.17.so
00007ff8da2e2000    1752     748       0 r-x-- libc-2.17.so
00007ff8da498000    2048       0       0 ----- libc-2.17.so
00007ff8da698000      16      16      16 r---- libc-2.17.so
00007ff8da69c000       8       8       8 rw--- libc-2.17.so
00007ff8da69e000      20      20      20 rw---   [ anon ]
00007ff8da6a3000      12       8       0 r-x-- libdl-2.17.so
00007ff8da6a6000    2044       0       0 ----- libdl-2.17.so
00007ff8da8a5000       4       4       4 r---- libdl-2.17.so
00007ff8da8a6000       4       4       4 rw--- libdl-2.17.so
00007ff8da8a7000     148     124       0 r-x-- libtinfo.so.5.9
00007ff8da8cc000    2048       0       0 ----- libtinfo.so.5.9
00007ff8daacc000      16      16      16 r---- libtinfo.so.5.9
00007ff8daad0000       4       4       4 rw--- libtinfo.so.5.9
00007ff8daad1000     132     116       0 r-x-- ld-2.17.so
00007ff8dacd6000      12      12      12 rw---   [ anon ]
00007ff8dace8000       4       4       4 rw---   [ anon ]
00007ff8dace9000      28      24       0 r--s- gconv-modules.cache
00007ff8dacf0000       8       8       8 rw---   [ anon ]
00007ff8dacf2000       4       4       4 r---- ld-2.17.so
00007ff8dacf3000       4       4       4 rw--- ld-2.17.so
00007ff8dacf4000       4       4       4 rw---   [ anon ]
00007fff03414000     132      28      28 rw---   [ stack ]
00007fff0345c000       8       4       0 r-x--   [ anon ]
ffffffffff600000       4       0       0 r-x--   [ anon ]
---------------- ------- ------- -------
total kB          116564    3436    1640

各字段为

Address:   start address of map,起始地址
Kbytes:    size of map in kilobytes,占用内存大小
RSS:       resident set size in kilobytes,常驻内存集
Dirty:     dirty pages (both shared and private) in kilobytes,脏页
	脏页:在内存中完成修改单但尚未同步至磁盘中的页面数据
Mode:      permissions on map: read, write, execute, shared, private (copy on write),访问权限
Mapping:   file backing the map, or ’[ anon ]’ for allocated memory, or  ’[ stack ]’ for the program stack,映射
Offset:    offset into the file,偏移量
Device:    device name (major:minor),设备

该命令即展示的/proc/PID/maps文件内容:

[root@localhost ~]# cat /proc/7673/maps
00400000-004dd000 r-xp 00000000 fd:00 134385557                          /usr/bin/bash
006dc000-006dd000 r--p 000dc000 fd:00 134385557                          /usr/bin/bash
006dd000-006e6000 rw-p 000dd000 fd:00 134385557                          /usr/bin/bash
006e6000-006ec000 rw-p 00000000 00:00 0
01314000-0147e000 rw-p 00000000 00:00 0                                  [heap]
7ff8d3baf000-7ff8da0d6000 r--p 00000000 fd:00 202070827                  /usr/lib/locale/locale-archive
7ff8da0d6000-7ff8da0e1000 r-xp 00000000 fd:00 202070798                  /usr/lib64/libnss_files-2.17.so
7ff8da0e1000-7ff8da2e0000 ---p 0000b000 fd:00 202070798                  /usr/lib64/libnss_files-2.17.so
7ff8da2e0000-7ff8da2e1000 r--p 0000a000 fd:00 202070798                  /usr/lib64/libnss_files-2.17.so
7ff8da2e1000-7ff8da2e2000 rw-p 0000b000 fd:00 202070798                  /usr/lib64/libnss_files-2.17.so
7ff8da2e2000-7ff8da498000 r-xp 00000000 fd:00 202070780                  /usr/lib64/libc-2.17.so
7ff8da498000-7ff8da698000 ---p 001b6000 fd:00 202070780                  /usr/lib64/libc-2.17.so
7ff8da698000-7ff8da69c000 r--p 001b6000 fd:00 202070780                  /usr/lib64/libc-2.17.so
7ff8da69c000-7ff8da69e000 rw-p 001ba000 fd:00 202070780                  /usr/lib64/libc-2.17.so
7ff8da69e000-7ff8da6a3000 rw-p 00000000 00:00 0
7ff8da6a3000-7ff8da6a6000 r-xp 00000000 fd:00 202070786                  /usr/lib64/libdl-2.17.so
7ff8da6a6000-7ff8da8a5000 ---p 00003000 fd:00 202070786                  /usr/lib64/libdl-2.17.so
7ff8da8a5000-7ff8da8a6000 r--p 00002000 fd:00 202070786                  /usr/lib64/libdl-2.17.so
7ff8da8a6000-7ff8da8a7000 rw-p 00003000 fd:00 202070786                  /usr/lib64/libdl-2.17.so
7ff8da8a7000-7ff8da8cc000 r-xp 00000000 fd:00 208614866                  /usr/lib64/libtinfo.so.5.9
7ff8da8cc000-7ff8daacc000 ---p 00025000 fd:00 208614866                  /usr/lib64/libtinfo.so.5.9
7ff8daacc000-7ff8daad0000 r--p 00025000 fd:00 208614866                  /usr/lib64/libtinfo.so.5.9
7ff8daad0000-7ff8daad1000 rw-p 00029000 fd:00 208614866                  /usr/lib64/libtinfo.so.5.9
7ff8daad1000-7ff8daaf2000 r-xp 00000000 fd:00 202070773                  /usr/lib64/ld-2.17.so
7ff8dacd6000-7ff8dacd9000 rw-p 00000000 00:00 0
7ff8dace8000-7ff8dace9000 rw-p 00000000 00:00 0
7ff8dace9000-7ff8dacf0000 r--s 00000000 fd:00 92160                      /usr/lib64/gconv/gconv-modules.cache
7ff8dacf0000-7ff8dacf2000 rw-p 00000000 00:00 0
7ff8dacf2000-7ff8dacf3000 r--p 00021000 fd:00 202070773                  /usr/lib64/ld-2.17.so
7ff8dacf3000-7ff8dacf4000 rw-p 00022000 fd:00 202070773                  /usr/lib64/ld-2.17.so
7ff8dacf4000-7ff8dacf5000 rw-p 00000000 00:00 0
7fff03414000-7fff03435000 rw-p 00000000 00:00 0                          [stack]
7fff0345c000-7fff0345e000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

glances

该命令是一个跨平台的交互式系统监视器工具,使用格式为glances [OPTIONS],常用选项为

--disable-XXX:关闭某模块的显示
-b:以Byte为单位显示网卡速率
-t #:指定刷新时间间隔
-1:单独显示每个CPU的统计数据
--export-XXX /PATH/TO/FILE:设定导出信息,保存到文件,如
	glances --export-csv /root/glances

其输出如下

glances

glances命令支持的子命令

a  Sort processes automatically          b  Bytes or bits for network I/O
c  Sort processes by CPU%                l  Show/hide alert logs
m  Sort processes by MEM%                w  Delete warning alerts
u  Sort processes by USER                x  Delete warning and critical alerts
p  Sort processes by name                1  Global CPU or per-CPU stats
i  Sort processes by I/O rate            I  Show/hide IP module
t  Sort processes by TIME                D  Enable/disable Docker stats
d  Show/hide disk I/O stats              T  View network I/O as combination
f  Show/hide filesystem stats            U  View cumulative network I/O
n  Show/hide network stats               F  Show filesystem free space
s  Show/hide sensors stats               g  Generate graphs for current history
2  Show/hide left sidebar                r  Reset history
z  Enable/disable processes stats        h  Show/hide this help screen
3  Enable/disable quick look plugin      q  Quit (Esc and Ctrl-C also work)
e  Enable/disable top extended stats
/  Enable/disable short processes name
0  Enable/disable Irix process CPU

此外,改命令可运行于C/S模式

服务模式:
	-s:服务器模式
	-B IP:设定本机IP,用于监听
	
	如:glances -s -B 192.168.18.128
	
客户端模式
	-c:客户端模式
	
	如:glances -c 192.168.18.128

dstat

该命令名可理解为Data Stat,用于生成系统资源数据,使用格式为

dstat [-afv] [options..] [delay [count]]

	#:刷新时间
		M N:每M秒刷新一次,刷新N次
	
	-c:显示CPU相关信息
		-C #,#,…,tatal:指定显示哪一个CPU信息
	-d:显示磁盘相关信息
		-D sda,sdb,…,total:指定显示哪个磁盘
	-g:显示page相关速率数据
	-m:memory相关统计数据
	-n:Interface相关统计数据
	-p:process相关统计数据
	-r:IO请求相关统计数据
	-s:swap相关统计数据
	
	--tcp
	--udp
	--raw
	--socket
	
	--ipc
	
	-top-cpu:显示最占用CPU的进程
	--top-io:显示最占用IO的进程
	--top-mem:显示最占用内存的进程
	--top-latency:显示延迟最大的进程

pstree

pstree即Process Tree,上文已有用到,用于查看进程树

[root@localhost ~]# pstree
systemd─┬─ModemManager───2*[{ModemManager}]
        ├─NetworkManager─┬─dhclient
        │                └─3*[{NetworkManager}]
        ├─2*[abrt-watch-log]
        ├─abrtd
        ├─agetty
        ├─alsactl
        ├─atd
        ├─auditd─┬─audispd─┬─sedispatch
        │        │         └─{audispd}
        │        └─{auditd}
        ├─bluetoothd
        ├─chronyd
        ├─crond
        ├─dbus-daemon───{dbus-daemon}
        ├─dmeventd───2*[{dmeventd}]
        ├─irqbalance
        ├─lsmd
        ├─lvmetad───{lvmetad}
        ├─master─┬─pickup
        │        └─qmgr
        ├─polkitd───5*[{polkitd}]
        ├─rngd
        ├─rsyslogd───2*[{rsyslogd}]
        ├─smartd
        ├─sshd─┬─sshd───bash
        │      └─sshd───bash───pstree
        ├─systemd-journal
        ├─systemd-logind
        ├─systemd-udevd
        ├─tuned───4*[{tuned}]
        └─vmtoolsd───{vmtoolsd}

kill

该命令用于向进程发送信号,使用格式为kill [SIGNAL] PID,默认发送15信号

在这里,信号可使用以下方式指定:

  • 信号号码,如:kill -1
  • 信号名称,如:kill -SIGKILL
  • 信号名称简写(即去掉名称的SIG),如:kill -KILL

向多个进程发送信号,可使用killall -SIGNAL PROCESS_NAME,也可使用killall命令,向指定进程名的所有进程发送信号

要终止后台作业,可使用

kill %JOB_ID

pgrep、pkill

pgrep命令用于查看进程ID,pkill命令用于向进程发送信号,二者的选项类似,均可基于模式进程匹配,使用格式为

pgrep [option] pattern
pkill [option] pattern

	-u	指定euid(effective user)(有效ID程序的属主ID)
	-U	指定uid(real user)(进程发起人的ID)
	-t	指定终端
	-l	显示进程名
	-a	显示完整格式的进程名
	-P	显示其父进程为指定进程的进程列表

pidof

该命令类似于pgrep,可根据程序名称,查找其相关进程的PID

free

free即“空闲”之意,用于查看系统上物理内存和交换空间的使用情况,如

[root@localhost ~]# free
              total        used        free      shared  buff/cache   available
Mem:        1870512      212380     1399964        9308      258168     1446688
Swap:       2097148           0     2097148

使用-m选项可以以MB为单位显示,而-g可以GB为单位显示

[root@localhost ~]# free -m
              total        used        free      shared  buff/cache   available
Mem:           1826         207        1366           9         252        1412
Swap:          2047           0        2047
[root@localhost ~]# free -g
              total        used        free      shared  buff/cache   available
Mem:              1           0           1           0           0           1
Swap:             1           0           1

关于swap上文已有介绍,使用方式见 Linux存储管理-Swap分区

top

该命令用于显示Linux会话,输出如下

top - 13:09:33 up 49 min,  2 users,  load average: 0.00, 0.01, 0.05
Tasks: 406 total,   2 running, 404 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.1 sy,  0.0 ni, 99.8 id,  0.1 wa,  0.0 hi,  0.1 si,  0.0 st
KiB Mem :  1870512 total,  1461928 free,   182164 used,   226420 buff/cache
KiB Swap:  2097148 total,  2097148 free,        0 used.  1498500 avail Mem
==================================================================================
   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
==================================================================================
   291 root      20   0       0      0      0 S   0.3  0.0   0:04.94 kworker/0:1
  8142 root      20   0  148496   2368   1448 R   0.3  0.1   0:00.03 top
     1 root      20   0   44016   6516   3928 S   0.0  0.3   0:02.87 systemd
     2 root      20   0       0      0      0 S   0.0  0.0   0:00.08 kthreadd
     3 root      20   0       0      0      0 S   0.0  0.0   0:00.21 ksoftirqd/0
     5 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/0:0H
     7 root      rt   0       0      0      0 S   0.0  0.0   0:00.16 migration/0
     8 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcu_bh
     9 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/0
    10 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/1
    11 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/2
    12 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/3
    13 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/4
    14 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/5
    15 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/6
    16 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/7
    17 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/8
    18 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/9
    19 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/10
    20 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/11
    21 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/12
    22 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/13
    23 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/14
    24 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/15
    25 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/16
    26 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/17
    27 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/18
    28 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/19
    29 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/20
    30 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/21
    31 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/22
    32 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcuob/23

输出信息的上方内容

当前系统时间
运行时长
登录的用户数
load average(平均负载),队列长度越小,证明CPU负载越低
	过去1分钟内的平均队列长度
	过去5分钟内的平均队列长度
	过去15分钟内的平均队列长度
	
(以上信息也可使用uptime命令查看)

Tasks 所有进程的相关信息
	total 进程总数
	running 处于运行状态的
	sleeping 处于睡眠状态的
	stopped 停止的
	zombie 僵死状态的

%Cpu(s) 每一个CPU的负载情况
	默认是Cpu(s),显示总体情况,按1可以展开显示每一个CPU的情况,各字段如下
字段说明
us用户空间(user space)占据的百分比
sy内核空间占据的百分比
ni调整nice值影响的百分比
id空闲的(idle)百分比
wa等待(waite)I/O所占据的时间
hi硬件中断(hard interrupt)占据的时间
si软中断占据的时间
st被偷走(steal)的时间4
KiB Mem 内存情况
	总数
	已用数
	空闲数
	buffer/cache数
	
Swap 交换空间情况
	总数
	已用数
	空闲数
	cache数

下方列表字段

PID
USER
PR:priority 优先级
	RT表示实时优先级
NI:nice值
VIRT:虚拟内存集(VSZ)
RES:常驻内存集(resident size)
SHR:Shared,共享内存大小
S:state,状态
	S:睡眠
	R:运行或就绪
%CPU:占的CPU百分比
%MEM:占的内存百分比
TIME:运行CPU时长
COMMAND:进程名

top命令同样支持交互式子命令

M:根据驻留内存大小进行排序
P:根据CPU使用百分比进行排序
T:根据累计运行时间进行排序

l:是否显示uptime信息(平均负载和启动时间),即第一行
t:是否显示tasks信息(进程和CPU状态相关信息),即第二与第三行
m:切换显示内存相关功能

s: 修改top命令刷新时间

c:是否显示完整的命令行信息
q:退出top
k:终止某个进程

z:彩色显示

该命令的常用选项:

-d #:指定刷新时间间隔,单位:s
-b:批模式显示
-n #:在批模式下,指定共显示多少批

uptime

该命令用于显示系统时间、运行时长几平均负载,如

[root@localhost ~]# uptime
 13:20:34 up  1:00,  2 users,  load average: 0.05, 0.04, 0.05

load average:过去1分钟、5分钟、15分钟的平均负载,即等待运行的进程队列的长度

htop

该命令也是一个交互式进程监视器,支持鼠标,其常用选项为

-d # :指定延迟时间间隔
-u USERNAME:仅显示指定用户的进程
-s COLUME:以指定字段进行排序

不带选项的htop命令输出如下
htop

交互式子命令:

u		选择指定用户的进程
l		显示进程所打开的文件列表
s		显示进程执行的系统调用
a		指定CPU的affinity,即绑定进程到指定的CPU上执行
#		快速将光标定位至指定的PID进程上
F5或t		以树状显示
F2		设定

P		按CPU占用百分比排序
M		按内存占用百分比排序
T		按时间排序
I		逆序排序
>		指定排序依据

nice/renice

Linux内核划分了140种优先级,其值为0-139,值越小表示优先级越高,分为两部分

  • 1-99:实时(Realtime)优先级,有内核调整
  • 100-139:静态(Static)优先级,用户可调整

用户可通过调整一个被称为“nice”的参数来管理进程的优先级,其范围为-20~19,分别对应优先级100~139

默认每一个进程的nice值都是0,其默认优先级为120

普通用户只能调大进程的nice值,管理员可以随意调整

  • 调整已经启动的进程的nice值:renice NI PID

  • 在启动时指定nice值:nice -n NI COMMAND

作业控制

在Linux中,前台(foreground)作业占据了命令提示符,后台(background)作业在启动之后,释放命令提示符,后续的操作在后台完成

非守护进程类的程序,启动以后都在前台工作

  • 前台 —> 后台
    • 已经启动的程序
      Ctrl+z:把正在前台的作业总到后台,默认送往后台的进程会处于停止状态
    • 尚未启动的程序
      COMMAND &:让命令直接在后台执行

    退出当前会话,作业也会终止,因为作业依然与当前终端相关

    若把作业送往后台,不期望作业随终端结束而终止

    • nohup COMMAND &
  • 后台 —> 前台
    • fg(ForeGround):将后台的作业调回前台
    • fg [[%]JOBID]%表示是作业号,由于bgfg无法操作进程,故可以省略
    • bg(BackGround):让后台的停止作业继续在后台运行
    • bg [[%]JOBID]:若省略JOBID,则运行带+的作业
jobs

查看后台的所有作业

作业号,不同于进程号
	+:命令将默认操作的作业
	-:命令将第二个默认操作的作业

vmstat

该命令用于查看系统状态,输出如下

[root@localhost ~]# vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0      0 1388328   2964 272524    0    0     9     1   15   22  0  0 100  0  0

字段说明:

procs
	r:运行或等待CPU时间片的队列长度
	b:处于不可中断睡眠的进程合数,即阻塞(通常为等待IO完成)队列长度
memory
	swpd:从物理内存交换至swap中的主机量
	free:空闲物理内存
	buff:buffer空间大小,通常与缓存写操作相关
	cache:cache空间大小,通常与缓存读操作相关
swap
	si:swap in,在观察时间内,有多少物理内存放到交换内存,通常是速率,kb/s
	so:swap out,在观察时间内,有多少交换内存放到物理内存,通常是速率,kb/s
io:
	bi:block in,从块设备读入的数据量,通常是速率,kb/s
	bo:block out,保存至块设备中的数据量,通常是速率,kb/s
system
	in:interrupt,中断发生速率,每秒钟的中断数
	cs:contest switch,上下文切换数,每秒钟切换的次数
cpu
	us:user space,用户空间占据的百分比
	sy:system,内核空间占据的百分比
	id:空闲的(idle)百分比
	wa:等待(waite)I/O所占据的时间
	st:被偷走(stolen)的时间

常用选项

#		每#秒刷新一次
N M		每N秒显示一次,但只显示M次
-s		显示内存统计数据

  1. 表格内容参考自 https://blog.csdn.net/wenqian1991/article/details/40110703 ↩︎

  2. 详见DNS相关介绍 ↩︎

  3. 关于如何使用swap,详见swap分区内容:https://blog.csdn.net/xiyangyang410/article/details/85857190#4_swap_732 ↩︎

  4. 虚拟化相关,后续将介绍 ↩︎

  • 3
    点赞
  • 0
    评论
  • 5
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值