本文主要介绍了网络与进程的相关内容以及在Linux上如何进行网络与进程管理,包括以太网介绍,TCP/IP,网络分层模型,IP地址的规划;同时介绍了Linux内核在进程管理方面的相关机制
此处的网络指以太网(Ethernet),它由Xerox的PARK实验室研发,并且免费提供
关于网络我们并不陌生,故此处仅作简要介绍
在网络诞生初期,只有同一厂商生产的设备可能相互通信,为打破这种窘境,20世纪70年代末,ISO(International Organization for Standardization,国际标准化组织)设计了OSI(Open System Interconnection,开放系统互联)参考模型,而如今大量使用的,我们将其称为TCP/IP协议栈,即DoD模型
OSI(Open System Interconnection,开放系统互联),是一种概念模型,故将其称为“参考模型”,定义于ISO/IEC 7498-1。它旨在以协议的形式帮助不同厂商的设备进行相互通信
将网络通信的过程划分为更小、更简单的组件,有助于开发、设计与排障等
通过标准化网络组件,让多家厂商能够协同开发
定义了模型每层执行的功能,从而鼓励了行业标准化
让不同类型的网络硬件与软件能够彼此通信
避免对一层的修改影响到其他层
再次说明,该模型并非具体的协议,它是一种思想,是指导原则,开发人员可根据该思想可开发能够实现网络互连的应用
该模型包含7层,其中上3层指定了终端中的应用如何彼此通信以及如何与用户交互,属于资源子网(Resources Subnet)的范畴;而下4层定义了如何进行端到端的数据传输,属于通信子网(Communication Subnet)
应用层 |
---|
表示层 |
会话层 |
传输层 |
网络层 |
数据链路层 |
物理层 |
应用层(Application Layer)提供为应用软件而设的接口,以设置与另一应用软件之间的通信。例如: HTTP,HTTPS,FTP,TELNET,SSH,SMTP,POP3等。
第6层 表达层
主条目:表达层
表达层(Presentation Layer)把数据转换为能与接收者的系统格式兼容并适合传输的格式。
会话层(Session Layer)负责在数据传输中设置和维护计算机网络中两台计算机之间的通信连接。
传输层(Transport Layer)把传输表头(TH)加至数据以形成数据包。传输表头包含了所使用的协议等发送信息。例如:传输控制协议(TCP)等。
网络层(Network Layer)决定数据的路径选择和转寄,将网络表头(NH)加至数据包,以形成分组。网络表头包含了网络数据。例如:互联网协议(IP)等。
数据链路层(Data Link Layer)负责网络寻址、错误侦测和改错。当表头和表尾被加至数据包时,会形成帧。数据链表头(DLH)是包含了物理地址和错误侦测及改错的方法。数据链表尾(DLT)是一串指示数据包末端的字符串。例如以太网、无线局域网(Wi-Fi)和通用分组无线服务(GPRS)等。
分为两个子层:LLC(logical link control,逻辑链路控制)子层和MAC(media access control,介质访问控制)子层。
物理层(Physical Layer)在局部局域网上传送数据帧(data frame),它负责管理计算机通信设备和网络媒体之间的互通。包括了针脚、电压、线缆规范、集线器、中继器、网卡、主机接口卡等。
每一层都有其实现的协议,如
数据包利用网络在不同设备之间传输时,为了可靠和准确地发送到目的地,并且高效地利用传输资源(传输设备和传输线路),事先要对数据包进行拆分和打包,在所发送的数据包上附加上目标地址,本地地址,以及一些用于纠错的字节,安全性和可靠性较高时,还要进行加密处理等等。这些操作就叫数据封装(Data Encapsulation)
OSI模型每一层都对数据进行封装来形成PDU(Protocol Data Unit,协议数据单元),PDU包含来自上层的信息和当前层的实体附加的信息,这个PDU会被传送到下一较低的层
每一层附加到PDU上的信息,是指定给另一个系统的同等层的,这就是对等层进行一次通信会话协调的过程,即
而其中每层的 PDU 一般由本层的协议头、协议尾和数据封装构成
而数据解封与此相反
在传输层用TCP头已标示了与一个特定应用的连接,并将数据封装成了数据段(Segment)
网络层则用IP头标示了已连接的设备网络地址,并可基于此信息进行网络路径选择,此时将数据封装为数据包(Package)
到了数据链路层,数据已封装成了数据帧(Frame),并用MAC头给出了设备的物理地址,当然还有数据校验等功能字段等
互联网协议套件(英语: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和信道通常预先建好,并且它们有一些直接发送到实体接口所没有的特殊特点(例如,它可以加密经过它的数据)。由于现在链路“层”是一个完整的网络,这种协议组的递归使用可能引起混淆。但是它是一个实现常见复杂功能的一个优秀方法。(尽管需要注意预防一个已经封装并且经隧道发送下去的数据包进行再次地封装和发送)
下图为二者的各层的大致对应关系
CSMA/CD(Carrier-Sense Multiple Access with Collision Detection,带有冲突检测的载波侦听多路访问)是以太网使用的重要机制,这是一种帮助设备均衡地共享带宽的协议,可避免两台设备同时在网络介质上传输数据
如图,主机与通过网络传输数据时,首先检测线路上是否有数字信号,若没有其他主机传输数据,该主机将开始传输数据,并且在传输过程中,传输主机将持续监听线路,确保没有其他主机开始传输
若该主机在线路上检测到其他信号,将发送一个扩展的拥堵信号(Jam Signal),使网段上的所有节点都不再发送数据。检测到拥堵信号后,其他节点将等待一段时间再尝试传输。后退算法决定了发生冲突的工作站多长时间后可重新传输
该机制工作大致流程为:
此处将重要的协议首部列出,以供参考
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 port | Destination port | ||||||||||||||||||||||||||||||
4 | 32 | Length | Checksum |
当UDP运行在IPv4之上时,为了能够计算校验和,需要在UDP数据包前添加一个“伪头部”。伪头部包括了IPv4头部中的一些信息,但它并不是发送IP数据包时使用的IP数据包的头部,而只是一个用来计算校验和而已
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的帧
上文已有介绍,TCP(Transmission Control Protocol,传输控制协议),是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能
我们习惯上将TCP连接描述为三次握手与四次断开,如下图
FSM(Finite State Machine,有限状态机)又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型
而TCP FSM即TCP有限状态机,可以描述为TCP连接的“生命阶段”。一个TCP设备与另一个TCP设备之间的每个连接在没有连接的空状态下开始,然后继续通过一系列状态直到建立连接。它保持在该状态,直到某些事情发生导致连接再次关闭,此时它继续通过另一个过渡状态序列并返回到关闭状态
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 |
各状态之间的转换如下图
我们之前有提到过,数据在传输时,经过通信子网的每一层都会添加相应协议的首部,而其中有一个重要信息,即源地址与目标地址,用于记录通信双方
而在不同的层中,“地址”的概念亦不相同,如
此处将对IP做简要介绍
IP(Internet Protocol),网际协议,也称为互联网协议。是在TCP/IP协议族中网络层的主要协议,任务仅仅是根据源主机和目的主机的地址来传送数据。为此目的,IP定义了寻址方法和数据报的封装结构。现有IPv4与IPv6两个版本,此处介绍IPv4
该协议工作在网络层,而该层的其他协议可以说都是为其提供支持的。数据在IP互联网中传送时会被封装为数据包
IP提供了一种“不可靠的”数据包传输机制(也被称作“尽力而为”或“尽最大努力交付”);也就是说,它不保证数据能准确的传输。数据包在到达的时候可能已经损坏,顺序错乱(与其它一起传送的报文相比),产生冗余包,或者全部丢失。如果应用需要保证可靠性,一般需要采取其他的方法,例如利用IP的上层协议控制
即互联网协议地址(Internet Protocol Address)又译为网际协议地址,是分配给网络上使用网际协议(IP) 的设备的数字标签。常见的IP地址分为IPv4与IPv6两大版本
从某种意义上说,IP(网际协议)是“掌控全局”的,它了解所有互联的网络,这是因为网络中的所有设备都有一个逻辑地址,这就是IP地址,IP是软件地址,而非硬件地址,硬件地址被硬编码到NIC(Network Interface Card)中,用于在本地网络中寻找主机(即MAC)
IPv4地址长32位,被划分为4组,可使用三种方式表示
以上例子中表示的是同一个地址,日常中我们常用点分十进制与二进制表示
而若按照IP的设计,一共有 2 32 2^{32} 232个地址,将其按照一层逻辑结构编址,在路由选择时将非常低效,鉴于此,我们将IP地址分为网络地址与主机地址(想象一下电话号码的区号)
网络地址唯一标识网络,在同一网络中,所有主机的IP地址都有相同的网络地址,而同一个网络内部的特定主机都有唯一为主机地址。如,对于192.168.1.10,192.168.1就是网络地址,10就是主机地址。而我只如何知道的呢?
最初人们工具网络规模创建网络分类,即对于少量包含大量节点的网络,创建了A类网络;另一种底端情况,创建了C类网络,即大量包含少量节点的网络,具体划分如下所示
类别 | 最大网络数 | IP地址范围 | 单个网段最大主机数 |
---|---|---|---|
A | 126(27-2) | 1.0.0.0-127.255.255.255 | 16777214 |
B | 16384(214) | 128.0.0.0-191.255.255.255 | 65534 |
C | 2097152(221) | 192.0.0.0-223.255.255.255 | 254 |
即二进制的IP地址为0开头的为A类网络,10开头的为B类网络,110的为C类网络
此外还有:1110开头的为D类网络,即224-239,为组播地址;1111开头的为E类地址,即240-255,用于科研,D类与E类网络我们这里用到不多
IP地址在设计之初,提供了私有IP地址,这些地址在互联网中不可被路由,同时也节省了IP地址空间,对于A、B、C类网络都有其私有IP地址,如下所示
IP地址区段 | IP数量 | 分类网络说明 | 最大CIDR区块(子网掩码) | 主机端位长 |
---|---|---|---|---|
10.0.0.0–10.255.255.255 | 16777216 | 单个A类网络 | 10.0.0.0/8 (255.0.0.0) | 24位 |
172.16.0.0–172.31.255.255 | 1048576 | 16个连续B类网络 | 172.16.0.0/12 (255.240.0.0) | 20位 |
192.168.0.0–192.168.255.255 | 65,536 | 256个连续C类网络 | 192.168.0.0/16 (255.255.0.0) | 16位 |
上文提到了网络分类,但有时由于各种原因,我们需要对网络进行再次分隔,即子网划分
比如,当一组IP地址指定给一个公司时,公司可能将该网络“分割成”小的网络,每个部门一个。这样,技术部门和管理部门都可以有属于它们的小网络。通过划分子网,我们可以按照我们的需要将网络分割成小网络。这样也有助于降低流量和隐藏网络的复杂性
划分子网后,通过使用掩码,把子网隐藏起来,使得从外部看网络没有变化,这就是子网掩码
子网掩码(Subnet Mask)又叫网络掩码、地址掩码、子网络遮罩,它是一种用来指明一个IP地址的哪些位标识的是主机所在的子网,以及哪些位标识的是主机的位掩码。子网掩码不能单独存在,它必须结合IP地址一起使用,即将某个IP地址划分成网络地址和主机地址两部分
并非所有网络都需要子网,故网络可以使用其默认的子网掩码
而上文的实例中,我们之所以能区分一个C类网络的网络地址与主机地址,就是这个原因,各类网络的默认子网掩码如下所示
网络 | 格式 | 默认子网掩码 |
---|---|---|
A类 | network.node.node.node | 255.0.0.0 |
B类 | network.network.node.node | 255.255.0.0 |
C类 | network.network.network.node | 255.255.255.0 |
VLSM(Variable Length Subnet Mask,可变长子网掩码)使用长度不同的子网掩码将网络划分为众多子网,适用于不同类型的网络设计,其主要实现为使用CIDR(Classless Inter-Domain Routing,无类别域间路由)和路由汇聚(route summary)来控制路由表的大小
我们从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个为子网地址与广播地址,他们不是合法的主机地址
有哪些子网:网络位可为1
或0
,故合法的网络位为0
和128
每个子网的广播地址:有两个子网,192.168.10.0/25
与192.168.10.128/25
对于第一个子网,所有主机位为1
为广播地址,即192.168.10.127/25
,对于第二个子网,则为192.168.10.255/25
每个子网的合法主机地址:
网 | 0 | 128 |
---|---|---|
第一个地址 | 1 | 129 |
最后一个地址 | 126 | 254 |
广播地址 | 127 | 255 |
100.0.0.16/28
对应网段的网络地址、广播地址、可分配IP地址范围:
该地址将IP的第四段的4位作为网络地址,故其网络地址为100.0.0.16
广播地址为主机位全部置1
,即100.0.0.31
该网络可用的IP地址为100.0.0.17
到100.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系统的命名方式如下
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个插槽上的设备
网卡设备的命名过程
udev
,辅助工具程序:/lib/udev/rename_device
,会根据/usr/lib/udev/rules.d/60-net.rules
文件中的信息,查询/etc/sysconfig/network-scripts/ifcfg-
开头的文件,查找HWADDR,将于实际设备的MAC地址对应的配置文件中DEVICE
的值设定为设备名
若第一步命名操作没有发生,且安装了biosdevname,biosdevname会根据/usr/lib/udev/rule.d/71-biosdevname.rules
中定义的规则对网络接口命名
若第一第二步没有发生,通过检测网络接口设备,根据/usr/lib/udev/rules.d/75-net-description
中的规则进行命名
ID_NET_NAME_ONBOAR
ID_NET_NAME_SLOT
ID_NET_NAME_PATH
如何回归传统命名方式
编辑/etc/default/grub配置文件
GRUB_CMDLINE_LINUX
参数加上一项net.ifnames=0
为grub2生成配置文件
grub2-mkconfig -o /etc/grub2.cfg
重启系统
另外, 可以使用设备名来直接引用设备
在红帽5中,网络设备名称使用别名,在/etc/modprobe.conf
文件中
在红帽6中,在/etc/udev/rules.d
目录中的70-persistent-net.rules
文件中定义
装卸载网卡驱动
modprobe -r MOD
modprobe MOD
在介绍配置之前,先了解一个概念:对应Linux而言,IP地址是属于内核的,因此只要当前系统有这个地址,不管他人从哪个网卡传入数据(如ping),内核都会响应
另外,这里先各工具与方式作以简要总结
net-tools
ifconfig:配置IP
route:路由
netstat:状态
iproute2
nm(CentOS 7)
DNS服务器指定
/etc/resolv.conf
本地主机名配置
hostname
配置文件:/etc/sysconfig/network
CentOS7:hostnamectl
RedHat相关发行版网络配置文件
/etc/sysconfig/network-scripts/ifcfg-NETCARD_NAME
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 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
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 mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10
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 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
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
ifconfig InterFace IP/MASK [up|down]
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
命令用于查看本机的路由表:
[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 | 意义 |
---|---|
U | route is up,启用状态 |
H | target is a host,主机路由 |
G | use gateway,网关路由 |
R | reinstate route for dynamic routing |
D | dynamically installed by daemon or redirect |
M | modified from routing daemon or redirect |
A | installed by addrconf |
C | cache entry |
! | reject route |
而查看路由表时,可以使用-n
选项,以数字方式显示各主机或端口等相关信息,不反解地址到主机名
而对于子命令,这里介绍add
与del
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 [ DEVICE [ :ALIAS: ] ] [ command ] ADDRESS [ LENGTH ] [ PEER ]
另外,还有两个脚本实现的命令,ifup
与ifdown
,这两个命令通过配置文件/etc/sysconfig/network-scripts/ifcfg-IFACE
来识别接口并完成配置,用法为
ifup CONFIG [boot]
ifdown CONFIG
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
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
,如link
,addr
,route
等
OBJECT
与COMMAMD
在不会引起混淆的情况下可以简写
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: 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 - 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 - 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 - 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工具的命令对比
在CentOS7中默认使用NetworkManager守护进程来监控和管理网络设置。nmcli
是命令行的NetworkManager工具,会自动把配置写到/etc/sysconfig/network-scripts/
目录
此外NetworkManager还提供一个TUI工具,即nmtui
,该命令用法较为简单,此处不过多介绍,其配置界面如下
此外,关于图形配置工具,还有setup
与system-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 ] [+|-].
修改IP地址等属性
nmcli connection modify IFACE [+|-]setting.property value
setting.property:
ipv4.address
iv4.gateway
ipv4.dns1
ipv4.method
manual
…
device
status
show
connect
disconnect
该命令是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
关于网络配置文件,位于/etc/sysconfig/network-scripts/
目录,分为两类:
ifcfg-eth#
ifcfg-ppp#
route-eth#
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 主机名 主机别名
配置修改完成后,需要重启网络服务生效:
service SERVICE {start|stop|restart|status}
service network restart
等效于执行:/etc/rc.d/init.d/network restart
systemctl {start|stop|restart|status} SERVICE[.service]
systemctl restart network.service
路由配置文件为/etc/sysconfig/network-scripts/route-IFACE
DEST via NEXTHOP
ADDRESS#=DEST
NETMASk#=MASK
GATEWAY#=Gateway
一组的#
应该使用相同的数字
两种格式不能混合使用
ping
send ICMP ECHO_REQUEST to network hosts
ping [OPTIONS] DESTINATION
-c # 指定请求的次数
-w DEADLINE 测试执行时长
-W TIMEOUT 超时时长
-s # 指定报文大小
traceroute
print the route packets trace to network host
获取从当前主机到达目标主机所有经过的网关
traceroute HOST
tracepath
traces path to a network host discovering MTU along this path
mtr
a network diagnostic tool
网络诊断工具
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
显示指定接口
选项与接口之间没有空格
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
query or control network driver and hardware settings
查询或控制网络驱动程序和硬件设置
ethtool [OPTIONS] DEVICE
-S 显示统计数据
autoneg {on|off} 是否开启自动协商功能
该工具是一个网络抓包分析工具,支持将信息保存到文件,其用法为
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
从程序的角度来看,内核可以被认为是一台增强的计算机,将计算机抽象到一个高层次上。应用程序只需发出指令,实际如何完成与应用程序是无关的,内核抽象了实现细节
当多个程序在同一系统中并发运行时,也可以将内核视为资源管理与调度程序,内核负责将可用的共享资源(如CPU时间、磁盘空间、网络资源等)分配到各个系统进程,同时需要保证系统的完整性
也可以将内核视为库,他提供了一组面向系统的命令。如下图,这里的库为Libraries,通常以API(Application Programming Interface,应用编程接口)的形式提供,是软件系统不同组成部分衔接的约定;此外,还有更底层的ABI(Application Binary Interface,应用二进制接口),定义了机器代码如何访问数据结构与运算程序,此处所定义的界面相当低级并且相依于硬件
在操作系统的实现方面,目前有两种主要类型
目前,Linux使用宏内核的设计规范,同时也借鉴了微内核的设计思想,通过模块,使得可以向内核动态添加或卸载功能,弥补了宏内核的一些缺陷
由于Linux是多任务系统,它支持并发执行的若干进程(用户看来如此),而系统中真正同时运行的进程数目最多不能超过CPU数目,因此内核会按照d短的时间间隔在不同的进程之间切换,如此就造成了同时处理多进程的假象
内核借助于CPU,负责进程切换的技术细节。通过在撤销进程的CPU资源之前保存进程所有与状态相关的要素,并将进程终于空闲状态;而在重新激活进程时,将保存的状态原样恢复。进程之间的切换称为进程切换
另外,内核还需要确定如何在现存进程之间共享CPU时间,重要的进程得到的CPU多一些,次要的少一些。确定哪个进程运行多长时间的过程称为调度
进程(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有两种创建新进程的机制,fork与exec
fork可创建当前进程的一个副本,父进程只有PID与子进程不同,在该系统调用(即fork)执行之后,系统中有两个进程,都执行同样的操作
exec将一个新程序加载到当前进程的内存中并执行,旧程序的内存页将刷出,其内容将替换为新的数据,而后开始执行新程序
Linux内核涉及进程和程序的所有算法都围绕数据结构task_struct建立,该结构定义在include/sched.h中。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)调度,分配给进程的时间片份额与其重要性相关
这种方式成为抢占式多任务(Preemptive Multitasking),各个进程都分配到一定的时间段可以执行,时间到期后,内核会从进程收回控制权,让另一个进程运行
被抢占的进程的运行时环境,即所有CPU寄存器的内容与页表,都会被保存,因此其运行结果不会丢失,在该进程恢复执行时,其环境可完全恢复
但是,若进程在某时刻可能因为无事可做而浪费CPU时间,这显然是不合理的,因此,当调度器在进程间切换时,需要指定每个进程的状态
进程可能有以下状态
已创建(Created):进程第一次创建时,即为已创建(或新建(New))状态,此状态下的进程将等待进入就绪状态,而在大部分操作系统中,这将是自动的
等待/就绪(Waiting/Ready):进程能够运行,但没有获得许可,因为CPU分配给了另一个进程,调度器可以在下一次任务切换时选择该进程
运行(Running):程序正在运行
阻塞(Blocked):进程在等待一个外部事件,该事件完成前进程无法继续
终止(Terminated):当进程运行完成自己的任务,或显式被杀死时,将进入终止状态
此外还有一种状态需要说明,即僵尸进程(Zombie Process),顾名思义,这样的进程进程已经死亡,但仍然以某种方式活着!即他们占用的资源(内存,占用的设备等)已经释放,而进程表中仍然有对应的表项
而僵尸进程产生的原因,在于Unix-Like操作系统下进程创建与销毁的方式。在以下两种事件发生时,进程将终止运行
SIGTERM
或SIGKILL
信号完成,这是正常的终止进程wait4
(wait for之意)系统调用,这相当于向内核证实父进程已经确认子进程的终结,该系统调用是的内核可以释放为子进程保留的资源而在第一个事件发生且第二个事件未发生时,就会出现“僵尸”进程,如图
在进程终止之后,其数据尚未从进程表删除前,进程就处于“僵死”态,如父进程没有发出wait调用,僵尸进程可能一直存在
当一个父进程由于正常完成工作而退出或由于其他情况被终止,它的一个或多个子进程却还在运行,那么那些子进程将成为孤儿进程。为避免孤儿进程退出时无法释放所占用的资源而僵死,进程号为1的init进程将会接受这些孤儿进程,这一过程也被称为“收养”(re-parenting)
进程并不是内核支持的唯一一种执行形式,除了重量级进程(也称为Unix进程)之外,还有一种形式,即线程(Thread)(有时也称为轻量级进程)
一般,一个进程可能由若干线程组成,这些线程共享同样的数据和资源,但可能执行程序中不同的代码。如今,线程概念已经集成到编程语言中,同时,在软件开发中,也有一些并行编程模型,如多进程、单进程多线程等
可以理解为,进程是一个正在执行的程序,而线程则是与主程序并行运行的程序函数或例程。由于线程和主程序共享同样的地址空间,主程序自动就可以访问接收到的数据,因此除了为防止线程访问同一内存区而采取的互斥机制外,就不需要什么通信了
从资源管理与分配角度来讲,Linux内核负责将底层应将的计算能力抽象化为系统调用,对上层提供,此处介绍CPU与内存资源的分配
由于内存区域是通过指针寻址,因此CPU的字长决定了所能管理的地址空间的最大长度。对于32位系统(如IA-32、PPC、m68k),其最大寻址能力为232=4GB;而对于64位系统(Alpha、IA-64、AMD64),则为264B
地址空间的最大长度与实际可用的物理内存数量无关,由此,也被称作虚拟地址空间。从系统中每个进程的角度来看,地址空间中只有自身一个进程,而无法感知到其他进程的存在
Linux将虚拟地址空间划分为两部分,即内核空间(Kernel Space)与用户空间(User Space)
系统中每个用户进程都有吱声的虚拟地址范围,从0到TASK_SIZE;而用户空间之上的区域(即TASK_SIZE到232或264)保留给内核使用,用户进程不得访问
TASK_SIZE是一个特定于计算机体系结构的常数,吧地址空阿金按照给定的比例划分为两部分。例如在IA-32系统中,系统空间在3GB处划分,因此每个进程的虚拟地址空间是3GB,内核就有1GB可用(虚拟地址空间的总长度为4GB)。以下以该架构为例说明
再次说明,这种划分的可用内存数与实际内存无关,由于地址空间虚拟化的结果,每个用户进程都认为自身有3GB的内存,而虚拟地址空间顶部的内核空间总是同样的,无论当前执行的是哪个进程
内核将虚拟地址空间划分为两个部分,因此能够保护各个同进程,使之彼此隔离。所有的现代CPU都提供了几种特权级别,进程可以驻留在某一特权级别
每个特权级别都有各种限制,例如对执行某些汇编语言指令或访问虚拟地址空间某一特定部分的限制
IA-32体系结构使用4种特权级别,即保护环(Protection Rings),内环可以访问更多的功能,如图
而Linux值使用两种不同的状态:内核态与用户态。两种状态的关键差别在对于改与TASK_SIZE的内存区域的访问,即在用户状态进制访问内核空间,用户进程不能操作或读取内核空间中的数据,也无法执行内核空间中的代码。该机制可防止进程无意间修改彼此的数据而造成的相互干扰
若普通进程想要执行任何影响整个系统的操作(如操作I/O),则只能借助于系统调用想内核发出请求。内核检查进程是否允许执行想要的操作,而后代表进程执行所需的操作,返回到用户状态
CPU大多数时间都在执行用户空间中的代码,当应用程序执行系统调用时,切换到核心态,内核将完成其请求,在此期间,内核可以访问虚拟地址空间中的用户部分,在系统调用完成后,CPU切换会用户状态,硬件中断也会使CPU切换到核心态,这种情况下内核不能访问用户空间
由于每个进程都有自身的虚拟地址空间,因此内核必须考虑如何将实际可用的物理内存映射到虚拟地址空间的区域,这种物理地址与逻辑地址的映射关系保存在一种叫页表(Page Table)
在该映射中,每个映射被称为PTE(Page Table Entry,分页表项),虚拟地址关系到进程的用户空间和内核空间,而物理地址则用来寻址实际可用的内存,如图
如图,虚拟空间内内核划分为很多等长的部分,称之为页,同样,物理内存页被划分为多个页,不过物理内存页一般为称为页帧(Page Frame)
实现两个地址空间的关联最容易的方式是使用数组,对虚拟内存空间的每一页,都分配一个数组项
而因为虚拟地址空间的大部分区域都没有使用,因而也没有关联到页帧,那么久可以使用多级分页
如图,计算机体系结构设计会将虚拟地址划分为多个部分,具体在何处划分依据不同的体系结构而已
Linux操作了四级页表,第一分部为PGD(Page Global Directory,全局页目录),用于索引进程中的一个数组(每个进程有且仅有一个),该数组即PGD,他指向另一些数组的起始地址,这些地址就是PUD(Page Upper Directory,上级页目录)
以此类推,PUD指向PMD(Page Middle Directory,中间页目录),PMD的数组项也是指针,指向下一级数据,称为页表或页目录,即第四部分PTE(Page Table Entry)
至此,虚拟内存页与页帧之间的映射就此完成,页表的数组项是直接指向页帧的
最后一部分为偏移量,他指定了页内部一个字节的位置,归根结底,每个地址都指向地址空间中唯一定义的某个字节
另外,CPU还提供一下两种机制来加速内存访问
在内核分配内存时,必须记录页帧的已分配或空闲状态,以避免两个进程使用相同的内存区域,另外,还需要保证该操作尽快完成
内核中很多是要要求分配连续页,为了快速检测内存中的连续区域,内核采用了一种叫做伙伴系统(Buddy System)的机制
系统中的空闲内存块总是两两分组,每组中的两个内存块称为伙伴(Buddy ),伙伴的分配可以是彼此独立的,但若两个伙伴都是空闲的,内核会将其合并为一个更大的内存块,作为下一层的某个内存块的伙伴
内核对所有大小相同的伙伴(1、2、4、8、16……)都放在同一个列表中管理
若系统需要8个页帧,则将16个页帧组成的块拆分为两个伙伴,其中一个块用来满足应用程序的请求,而剩余的8个页帧则放置到对应8页块大小内存块列表中
在应用释放内存时,内核可以直接检查地址,来判断能否创建一组伙伴,并合并为一个更大的内存块放回到伙伴列表中
内核本身经常需要比完整页帧小很多的内存块,由于内核无法使用标准库的函数,因而必须在伙伴系统的基础上自行定义额外的内存管理层,将伙伴系统划分为更小的部分
该方法不仅可以分配内存,还为频繁使用的小对象实现了一个一般性的缓存,即slab缓存,他使用两种方法分配内存
对频繁使用的对象,内核定义了只包含了所需类型对象实例的缓存,每次需要某种对象时,可以从对象的缓存快速分配,使用后释放到缓存。slab缓存自动维护与伙伴系统的交互,在缓存用尽时请求新的页帧
对通常情况下小内存块的分配,内核针对不同大小的对象定义了一组slab缓存,可以像用户空间编程一样,用相同的函数访问这些缓存。但是这些函数名都增加了前缀“k”,以表示是与内核相关联:kmalloc,kfree
slab与Buddy分配机制的关系如下图
页面交换通过利用磁盘空间作为扩展内存,从而增大了可用内存3
在内核需要更多内存时,不经常使用页可以写入磁盘,即LRU(Least Recently Used)机制。若再需要访问相关数据,内核会将相应的页切换会内存
通过缺页异常机制,这种切换操作对于程序而言是透明的。而页面回收用户将内存映射被修改的内存与底层的块设备同步,因此有时也被称为数据回写。数据刷出后,内核即可将页帧用于其他用途(类似于页面交换)
在Unix-Like操作系统中,使用Swap来描述在RAM和磁盘之间移动内存页面的行为,同时也使用Swap来表示存储页面的区域
若将磁盘的某个分区用于交换,则该分区叫做Swap分区(Swap Partitions),而专用于交换的硬盘称为交换驱动器(Swap Drive)、Scratch Drive、Scratch Disk等
而由于磁盘与RAM的速度差了几个数量级,加之使用机械存储设备会为硬盘带来几毫秒的延迟,因此,在实际可行的情况下,希望减少或消除交换
Linux提供了参数,该参数更改了交换运行时内存之间的平衡,而不是从系统页面缓存中删除页面:/proc/sys/vm/swappiness
许多类Unix操作系统(例如AIX,Linux和Solaris)允许并行使用多个存储设备用于交换空间,以提高性能
在介绍命令之前,再对上面的介绍作以补充
上文已有介绍,进程都是动态创建并由一个动态分配的 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);
进程数据文件系统(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系统中,进程主要由三种类型
IPC(Inter-Process Communication,进程间通信),指至少两个进程或线程间传送数据或信号的一些技术或方法
关于进程间通信的方式,本主题涉及到的主要为:
此处顺表一提,不同主机上的进程通信,一般可通过RPC(Remote Procedure Call,远程过程调用)或Socket进行
Linux系统上的常用信号,在Bash编程-信号捕捉中已有介绍,此处再次列出:
信号 | 值 | 描述 |
---|---|---|
1 | SIGHUP | 挂起进程,让一个进程不必重启即可重读其配置文件 |
2 | SIGINT | 中断进程,Ctrl+C |
9 | SIGKILL | 杀死进程 |
15 | SIGTERM | 终止一个进程 |
18 | SIGCONT | 调回后台进程 |
19 | SIGSTOP | 停止一个进程,即送往后台,Ctrl+Z |
可通过SIGNAL(7)查看更多信息
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
命令的选项有三种风格
-
-
--
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
输出字段说明:
字段 | 说明 |
---|---|
USER |
进程的属主 |
PID |
进程号 |
%CPU |
占用CPU的时间百分比 |
%MEM |
占用内存的空间百分比 |
VSZ |
Virtual memory SiZe,虚拟内存集 |
RSS |
ReSident Size,常驻内存集,不能放到交换内存中 |
TTY |
关联到的终端(? 表示与终端无关) |
STAT |
进程状态 |
START |
启动时间 |
TIME |
累计运行时长(占据CPU的时长) |
COMMAND |
哪个命令启动的进程(加[] 的表示是内核线程) |
此外,关于STAT
(进程状态),有以下几个
状态 | 描述 |
---|---|
D |
uninterruptable sleeping(usually IO),不可中断睡眠 |
R |
running or runnable(on run queue),运行或就绪 |
S |
interruptable Sleeping(waiting for an event to complete),可中断睡眠 |
T |
stopped by debugger during the tracing,停止 |
Z |
Zombie,僵死态 |
W |
|
X |
|
t |
|
< |
high-priority,高优先级进程 |
N |
low-priority,低优先级进程 |
+ |
前台进程组中的进程 |
l |
多线程进程 |
s |
Session leader,会话进程首进程 |
状态中W
、X
、t
如今在实际应用中看不到(除了程序员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
意为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 [OPTIONS]
,常用选项为
--disable-XXX:关闭某模块的显示
-b:以Byte为单位显示网卡速率
-t #:指定刷新时间间隔
-1:单独显示每个CPU的统计数据
--export-XXX /PATH/TO/FILE:设定导出信息,保存到文件,如
glances --export-csv /root/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
该命令名可理解为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
即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 [SIGNAL] PID
,默认发送15
信号
在这里,信号可使用以下方式指定:
kill -1
kill -SIGKILL
kill -KILL
向多个进程发送信号,可使用killall -SIGNAL PROCESS_NAME
,也可使用killall
命令,向指定进程名的所有进程发送信号
要终止后台作业,可使用
kill %JOB_ID
pgrep
命令用于查看进程ID,pkill
命令用于向进程发送信号,二者的选项类似,均可基于模式进程匹配,使用格式为
pgrep [option] pattern
pkill [option] pattern
-u 指定euid(effective user)(有效ID程序的属主ID)
-U 指定uid(real user)(进程发起人的ID)
-t 指定终端
-l 显示进程名
-a 显示完整格式的进程名
-P 显示其父进程为指定进程的进程列表
该命令类似于pgrep
,可根据程序名称,查找其相关进程的PID
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分区
该命令用于显示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 #:在批模式下,指定共显示多少批
该命令用于显示系统时间、运行时长几平均负载,如
[root@localhost ~]# uptime
13:20:34 up 1:00, 2 users, load average: 0.05, 0.04, 0.05
load average
:过去1分钟、5分钟、15分钟的平均负载,即等待运行的进程队列的长度
该命令也是一个交互式进程监视器,支持鼠标,其常用选项为
-d # :指定延迟时间间隔
-u USERNAME:仅显示指定用户的进程
-s COLUME:以指定字段进行排序
交互式子命令:
u 选择指定用户的进程
l 显示进程所打开的文件列表
s 显示进程执行的系统调用
a 指定CPU的affinity,即绑定进程到指定的CPU上执行
# 快速将光标定位至指定的PID进程上
F5或t 以树状显示
F2 设定
P 按CPU占用百分比排序
M 按内存占用百分比排序
T 按时间排序
I 逆序排序
> 指定排序依据
Linux内核划分了140种优先级,其值为0-139,值越小表示优先级越高,分为两部分
用户可通过调整一个被称为“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]
:%
表示是作业号,由于bg
和fg
无法操作进程,故可以省略bg
(BackGround):让后台的停止作业继续在后台运行bg [[%]JOBID]
:若省略JOBID
,则运行带+
的作业jobs
查看后台的所有作业
作业号,不同于进程号
+:命令将默认操作的作业
-:命令将第二个默认操作的作业
该命令用于查看系统状态,输出如下
[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 显示内存统计数据
表格内容参考自 https://blog.csdn.net/wenqian1991/article/details/40110703 ↩︎
详见DNS相关介绍 ↩︎
关于如何使用swap,详见swap分区内容:https://blog.csdn.net/xiyangyang410/article/details/85857190#4_swap_732 ↩︎
虚拟化相关,后续将介绍 ↩︎