「L2TP over IPSec」- 服务搭建(Libreswan + xl2tpd)

问题描述
搭建 L2TP/IPSec 的 VPN 服务时,在网上找了很多的教程都不是很好用,或多或少都存在问题,后来通过自动化脚本 vpnsetup.sh 完成了配置。
而这篇文章是通过分析 vpnsetup.sh 脚本后整理出来的,作为一个通用的配置教程(因为该脚本只支持 Ubuntu 和 Debian 的某些版本)。
解决方案
# 05/10/2022 该笔记创建于很久很久之前(2016?2017?2018?),当初是能够成功运行的,但是现在看来,这篇文章并没有太大价值。
补充说明
注意,不支持 OpenVZ 容器。不知道为什么,我们并未深入研究。
系统环境
Debian GNU/Linux 8.2 (jessie)
xl2tpd ppp
安装依赖的软件包

apt-get -yq install wget dnsutils openssl iptables iproute2 gawk grep sed net-tools

apt-get -yq install libnss3-dev libnspr4-dev pkg-config \
libpam0g-dev libcap-ng-dev libcap-ng-utils libselinux1-dev \
libcurl4-nss-dev flex bison gcc make libnss3-tools \
libevent-dev ppp xl2tpd

安装Libreswan服务

# Create and change to working dir
mkdir -p /opt/src && cd /opt/src

SWAN_VER=3.22
swan_file=”libreswan-$SWAN_VER.tar.gz”
swan_url1=”https://github.com/libreswan/libreswan/archive/v$SWAN_VER.tar.gz”
wget -t 3 -T 30 -nv -O “$swan_file” “$swan_url1”

/bin/rm -rf “/opt/src/libreswan-$SWAN_VER”
tar xzf “$swan_file” && /bin/rm -f “$swan_file”
cd “libreswan-$SWAN_VER”
[ “$SWAN_VER” = “3.22” ] && sed -i ‘/^#define LSWBUF_CANARY/s/-2$/((char) -2)/’ include/lswlog.h
sed -i ‘/docker-targets\.mk/d'[……]

READ MORE

「CRYPTOGRAPHY」- 密码学(计算机科学领域)

解决方案
整理如下内容的原因是:我们想要了解在密码学中涉及的知识内容。
《密码学基础,以色列,Oded Goldreich》
密码学涉及解决安全问题的计算系统的概念化、定义以及构造。密码系统的设计必须基于坚实的基础。
本书对这一基础问题给出了系统而严格的论述:用已有工具来定义密码系统的目标并解决新的密码问题。 本书集中讨论:计算复杂性(单向函数)、伪数以及零知识证明。 本书的重点在于澄清基本概念并论述解决密码问题的可行性,而不侧重于描述某种具体方法。 本书可作为密码学、应用数学、信息安全等专业的教材,也可作为相关专业人员的参考用书。
第1章 绪论 1 1.1 密码学:概述 1 1.2 概率论基础知识 6 1.3 计算模型 9 1.4 严密处理的目的 15 1.5 其他 第2章 计算复杂性 23 2.1 单向函数:动机(单向函数的意义) 24 2.2 单向函数的定义 25 2.3 弱单向函数隐含强单向函数 2.4 单向函数的多样性 2.5 核心断言(Hard-Core Predicates) 49 2.6 单向函数的有效放大 59 2.7 其他 67 第3章 伪发生器 77 3.1 启发性讨论 78 3.2 计算不可分辨性 79 3.3 伪序列发生器定义 85 3.4 基于单向置换的构造 94 3.5 基于单向函数的构造 103 3.6 伪函数 113 3.7 伪置换 124 3.8 其他 128 第4章 零知识证明系统 140 4.1 零知识证明:动机 141 4.2 交互证明系统 145 4.3 零知识证明:定义 4.4 NP零知识证明 169 4.5 否定结果 187 4.6 证据不可分辨性和隐藏性 192 4.7 知识证明 198 4.8 计算合理性证明(参数) 209 4.9 常数轮零知识证明 217 4.10 非交互零知识证明 225 4.11 多证明者零知识证明 234 4.12 其他 241 附录A 计算数论背景 250 附录B 第2卷摘要 256 参考文献
《密码学导引:原理与应用,德尔夫斯 (Delfs H.) 著 》
第1部分 密码学的基本概念 第1章 引言 3 1.1 加密与保密性 3 1.2 研究密码学的目的 4 1.3 攻击 5 1.4 密码协议 7 1.5 可证明安全 8 第2章 对称密钥加密体制 11 2.1 流密码 12 2.2 分组密码 14 2.2.1 DES 14 2.2.2 运行模式 17 习题 20 第3章 公钥密码学 22 3.1 公钥密码学基本概念 22 3.2 模算术 24 3.2.1 整数 24 3.2.2 整数模n 25 3.3 RSA 29 3.3.1 密钥生成与加密 29 3.3.2 数字签名 32 3.3.3 对RSA的攻击 33 3.3.4 RSA加[……]

READ MORE

「CS/CRYPTOGRAPHY」- 密码散列函数

数据认证的主要目的是确认数据是否被篡改,数据认证主要基于 Hash 算法; 数据通过 Hash 算法计算出一个唯一的 Hash 值,Hash 值携带在数据中转发给对端; 对端设备对数据重新进行 Hash,得出 Hash 值。将收到的 Hash 值与计算出的 Hash 值进行比对,一致说明没有被篡改;

散列算法:把任意长度的输入变换成固定长度的输出,h=H(M)
常见散列算法
1)MD5 (Message Digest Algorithm 5),通过输入任意长度的消息,产生 128bit 的消息摘要; 2)SHA (Secure Hash Algorithm),通过输入长度小于 264bit 的消息,产生 160bit 的消息摘要; 3)SM3 (Senlior Middle 3 )
MD5(信息认证代码)是计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护。将数据(如汉字)运算为另一固定长度值。其作用是让大量信息在用数字签名软件签署私人密钥前被“压缩”成一种保密的格式。除了可以用于数字签名,还可以用于安全访问认证;
SHA(安全哈希算法)主要适用于数字签名标准里面定义的数字签名算法;
SHA-1:安全散列算法 SHA(Secure Hash Algorithm)是由 NIST 开发的。在 1994 年对原始的 HMAC 功能进行了修订,被称为 SHA-1。SHA-1 在 RFC2404 中描述。SHA-1 产生 160 位的消息摘要。SHA-1 比 MD5 要慢,但是更安全。因为它的签名比较长,具有更强大的防攻破功能,并可以更有效的发现共享的密钥;SHA-1 的摘要长于 MD5,因而是更安全的。但是 SHA1 的计算过程比 MD5 更耗费时间和资源;
SHA-2:SHA-2 是 SHA-1 的加强版本,SHA-2 算法相对于 SHA-1 加密数据长度有所上升,安全性能要远远高于 SHA-1。SHA-2 算法包括 SHA2-256、SHA2-384 和 SHA2-512,密钥长度分别为 256 位、384 位和 512 位;
SM3(国密算法)是国家密码管理局编制的商用算法,用于密码应用中的数字签名和验证、消息认证码的生成与验证以及随机数的生成,可满足多种密码应用的安全需求;
以上几种算法各有特点,MD5 算法的计算速度比 SHA-1 算法快,而 SHA-1 算法的安全强度比 MD5 算法高,SHA-2、SM3 算法相对于 SHA-1 来说,加密数据位数的上升增加了破解的难度,使得安全性能要远远高于 SHA-1;
参考文献
Hash function – Wikipedia[……]

READ MORE

「CS/Cryptography」- 加密与解密(Encryption and Decryption)

问题描述
在 Internet 的传输中,基于 TCP/IP 协议栈封装的数据是明文传输的,这样就会存在很多潜在的危险。比如:密码、银行帐户的信息被窃取、入改,用户的身份被冒充,遭受网络恶意攻击等;
解决方案
在网络中应用加解密技术,可对传输的数据进行保护处理,降低信息泄漏的风险;
发展历程
1)Scytale:将纸张缠到木棒上,木棒为密钥,木棒粗细为密钥内容; 加密作为保障信息安全的一种方式,它不是现代才有的,它产生的历史相当久远,可以追溯到人类刚刚出现,并且尝试去学习如何通信的时候。他们不得不去寻找方法确保他们的通信的机密。但是最先有意识地使用一些技术方法来加密信息的可能是公元前五百年的古希腊人。他们使用的是一根叫 scytale 的棍子,送信人先绕棍子卷一张纸条,然后把要加密的信息写在上面,接着打开纸送给收信人。如果不知道棍子的宽度(这里作为密钥)是不可能解密信里面内容的;
2)凯撒密码:按照字母表,以进行字母转换; 大约在公元前 50 年,古罗马的统治者凯撒发明了一种战争时用于传递加密信息的方法,后来称之为“凯撒密码”。它的原理就是:将 26 个字母按自然顺序排列,并且首尾相连,明文中的每个字母都用其后的第三个字母代替,例如 Symantec 通过加密之后就变成 vBPdqwhf。(f(x)=(x+s)%26)
3)双轨算法:将明文中的奇数位和偶数位分别存放,对明文排序混乱,可实现⽆法直接读取明⽂内容。(双轨加密算法 – 百度文库) 近期加密技术主要应用于军事领域,如美国独立战争、美国内战和两次世界大战。在美国独立战争时期,曾经使用过一种“双轨”密码,就是先将明文写成双轨的形式,然后按行顺序书写;
4)密码机:运用密码对信息实施加(解)密处理和认证的专用设备。(密码机(一种在密钥作用下的装置)_百度百科) 在第一次世界大战中,德国人曾依靠字典编写密码,比如:10-4-2,就是某字典第 10 页,第 4 段的第 2 个单词。在二次世界大战中,最广为人知的编码机器是德国人的 Enigma 三转轮密码机,在二次世界大战中德国人利用它加密信息;
原理简述
加密是利用数学方法将明文(需要被隐项的数据)转换为密文(不可读的数据)从而达到保护数据的目的;

信息密码学 1)加密:明文变密文 2)信息明文 + 密钥 — C=En (K, P) –> 信息密文
特性特征
WIP
密钥管理技术
密钥管理技术 1)密钥产生 2)分配保存 4)更换与销毁
一个完整的密钥管理系统应该做到: 1)密钥难以被窃取和复制 2)即使窃取了密钥也没有用,密钥有使用范围和时间的限制 3)密钥的分配和更换过程对用户透明,用户不一定要亲自掌管密钥 4)核心密钥一定要采[……]

READ MORE

「CS/CRYPTOGRAPHY」- 加密技术分类

数据加密可以避免数据转发时被读取。数据加密一般有两种方案: 对称加密:使用同一个密码加密 / 解密,效率很高,但是对称加密在互相交互密钥时存在密钥被截取的风险; 非对称加密:使用公钥加密,私钥解密,安全性很高但是加解密效率很低;
对称密钥(Symmetric Key)
对称密钥技术:对称密钥加密,又称专用密钥加密,加密、解密用同一个密钥,即发送和接收数据的双方必使用相同的密钥对明文进行加密和解密运算;

对称加密算法,也叫传统密码算法(秘密密钥算法、单钥算法),加密密钥能从解密密钥中推算出来。发件人和收件人共同拥有同一个密钥,既用于加密也用于解密。对称密钥加密是加密大量数据的一种行之有效的方法。对称密钥加密有许多种算法,但所有这些算法都有一个共同的目的:以可以还原的方式将明文(未加密的数据)转换为暗文。由于对称密钥加密在加密和解密时使用相同的密钥,所以这种加密过程的安全性取决于是否有未经授权的人获得了对称密钥;

甲与乙事先协商好对称密钥,具体加解密过程如下: 1)甲使用对称密钥对明文加密,并将密文发送给乙; 2)乙接收到密文后,使用对称密钥对密文解密,得到最初的明文;
特别注意
希望使用对称密钥加密通信的双方,在交换加密数据之前必须先安全地交换密钥;
优点缺点
优点是: 1)效率高(加解密速度快),算法简单,系统开销小,适合加密大量数据;
缺点是,实现困难,扩展性差: 1)实现困难原因在于密钥分发问题:当进行安全通信前,需要以安全方式进行密钥交换; 2)扩展性差表现在:每对通信用户之间都需要协商密钥,n 个用户的团体就需要协商 n*(n-1)/2 个不同的密钥;
常见的对称加密算法
对称加密算法根据加密的对象不同,主要包括两类:流加密算法(Stream Algorithm);分组加密算法(Block Algorithm);
流加密算法:在算法过程中,连续输入元素,一次产生一个输出元素。典型的流密码算法一次加密一个字节的明文,密钥输入到一个伪随机字节生成器,产生一个表面随机的字节流,称为密钥流。流加密算法一般用在数据通信信道,浏览器或网络链路上;

常见的流加密算法:RC4 是 Ron Rivest 在 1987 年为 RSA Security 公司设计的流加密算法。它是密钥大小可变的流密码,使用面向字节的操作,就是实时的把信息加密成一个整体。该算法的速度可以达到 DES 加密的 10 倍左右;
分组加密算法:分组加密算法的输入为 明文分组 及密钥,明文被分为两半,这两半数据通过 n 轮处理后组合成密文分组,每轮的输入为上轮的输出;同时子密钥也是由密钥产生。典型分组长度是 64 位

分组算法包括以下几种:
1)数据[……]

READ MORE

「Networking」- Macvlan and IPvlan

TODO ! 网卡类型 ip link type
bridge – Ethernet Bridge device bond – Bonding device dummy – Dummy network interface hsr – High-availability Seamless Redundancy device ifb – Intermediate Functional Block device ipoib – IP over Infiniband device macvlan – Virtual interface base on link layer address (MAC) macvtap – Virtual interface based on link layer address (MAC) and TAP. vcan – Virtual Controller Area Network interface vxcan – Virtual Controller Area Network tunnel interface veth – Virtual ethernet interface vlan – 802.1q tagged virtual LAN interface vxlan – Virtual eXtended LAN ip6tnl – Virtual tunnel interface IPv4|IPv6 over IPv6 ipip – Virtual tunnel interface IPv4 over IPv4 sit – Virtual tunnel interface IPv6 over IPv4 gre – Virtual tunnel interface GRE over IPv4 gretap – Virtual L2 tunnel interface GRE over IPv4 erspan – Encapsulated Remote SPAN over GRE and IPv4 ip6gre – Virtual tunnel interface GRE over IPv6 ip6gretap – Virtual L2 tunnel interface GRE over IPv6 ip6erspan – Encapsulated Remote SPAN over GRE and IPv6 vti – Virtual tunnel interface nlmon – Netlink monitoring device ipvlan – Interface for L3 (IPv6/IPv4) based VLANs ipvtap – Interface for L3 (IPv6/IPv4) based VL[……]

READ MORE

「PATH OF A PACKET IN THE LINUX KERNEL STACK」

参考文献
Track a packet as it goes through the kernel (linux) Tracing packet in the Linux network stack Tracing a packet journey using Linux tracepoints, perf and eBPF PATHOFA PACKETINTHELINUXKERNELSTACK[……]

READ MORE

「conntrack-tools」

针对于系统管理员的用户空间的命令行程序。允许管理员查看和管理在内核中的连接追踪状态表(the in-kernel connection tracking state table),允许管理员与访问和操作连接追踪系统(Connection Tracking System),连接追踪系统为iptables提供了有状态的数据包检查。
该工具是用户空间的守护进程conntrackd和命令行界面conntrack: 1)用户空间守护进程conntrackd可用于启用基于群集的状态防火墙的高可用性并收集有状态防火墙使用的统计信息(尽管ulogd是日志记录的首选选项)。 2)命令行界面conntrack提供比传统的/proc/net/nf_conntrack更灵活的交互。
安装命令
从仓库中安装

# Kali GNU/Linux Rolling
apt-get install conntrack conntrackd

安装程序文件
conntrack:命令行程序,用于查看和管理连接状态。 conntrackd:守护进程。
参考文献
主页:http://conntrack-tools.netfilter.org dpkg -L conntrack, dpkg -L conntrackd[……]

READ MORE

「Linux」- TMP

自旋锁
在多处理器环境下,用于保护数据。
自旋锁锁住的进程一直旋转,而不是睡眠,因此能够用在中断等禁止睡眠的场景。
示例代码:

spin_lock(shost->host_lock);
shost->host_busy++;
spin_unlock(shost->host_lock);

信号量
类似于自旋锁,也是保护数据。
但是,如果无法获取信号量时,进程将进入睡眠状态 ⇒ 所以不能在中断中使用。
原子变量
原子变量提供 原子的、不可中断的 操作。如下所示:

atomic_t mapped

内核还提供系列源自变量操作函数:

atomic_add()
atomic_sub()
atomic_set()
atomic_read()[……]

READ MORE

「Linux」- 设备驱动(Device Drivers)

找到磁盘与ATA的对应关系

#!/bin/sh

ll /sys/class/ata_port/
ll /dev/disk/by-path

[WIP] Asking for cache data failed
What is a “Asking for cache data failed” warning?

[913914.442594] sd 7:0:0:0: [sdd] Asking for cache data failed
[913914.442597] sd 7:0:0:0: [sdd] Assuming drive cache: write through[……]

READ MORE

「Linux」- Interruption,硬中断、软中断

概念理解:中断(Interrupt)
中断是系统用来响应硬件设备请求的一种机制,它会打断进程的正常调度和执行,然后调用内核中的中断处理程序来响应设备的请求。
中断其实是一种异步的事件处理机制,可以提高系统的并发处理能力。
为了减少对正常进程运行调度的影响,中断处理程序就需要尽可能快地运行。如果中断要处理的事情很多,中断服务程序就有可能要运行很长时间。特别是中断处理程序在响应中断时,还会临时关闭中断。这就会导致上次中断处理完成之前,其他中断都不能响应,也就是说中断有可能会丢失。
为了解决中断处理程序执行过长和中断丢失的问题,Linux 将中断处理过程分成了两个阶段,也就是上半部和下半部: 上半部:用来快速处理中断,它在中断禁止模式下运行,主要处理跟硬件紧密相关的或时间敏感的工作;特点是快速执行;上半部会打断 CPU 正在执行的任务,然后立即执行中断处理程序。 下半部:用来延迟处理上半部未完成的工作,通常以内核线程的方式运行;特点是延迟执行;
以网卡收发数据为列: 1)网卡接收到数据包后,会通过硬件中断的方式,通知内核有新的数据到了,内核就应该调用中断处理程序来响应它 2)对上半部来说,快速处理,把网卡的数据读到内存中,然后更新硬件寄存器的状态(表示数据读取完成),最后再发送软中断信号,通知下半部做进一步的处理 3)下半部被软中断信号唤醒后,需要从内存中找到网络数据,再按照网络协议栈,对数据进行逐层解析和处理,直到把它送给应用程序
硬中断(Hardware interrupts)
上半部是发生硬件中断时调用,它不是软中断。
软中断(Software interrupts)
下半部则是软中断,下半部(软中断)以内核线程的方式执行,并且每个 CPU 都对应一个软中断内核线程,名字为 “ksoftirqd/<CPU N>”,比如说,0 号 CPU 对应的软中断内核线程的名字就是 ksoftirqd/0:

# ps aux | grep softirq
root 9 0.0 0.0 0 0 ? S Jul05 0:37 [ksoftirqd/0]
root 17 0.0 0.0 0 0 ? S Jul05 0:35 [ksoftirqd/1]
root 22 0.0 0.0 0 0 ? S Jul05 0:48 [ksoftirqd/2]
root 27 0.0 0.0 0 0 ? S Jul05 0:29 [ksoftirqd/3]

// 这[……]

READ MORE

「Linux」- Work Queues

Work Queue 类似与 tasklet,都用于延缓执行。但是 Work Queue 具有自己的 Process Context,能够休眠,也可被调度。
Kernel 初始化,会创建 kwventd_wq 工作队列,同时为其创建 Kernel Thread(每个 CPU 具有独立的内核线程)
Kernel 还提供 create_workqueue() 和 create_singlethread_workqueue() 函数,以允许用户创建自己的工作队列及执行线程。[……]

READ MORE

「Linux」- 内核模块编程

问题描述
我们将要学习 Linux Kernel Module 的开发方法,以为学习 Linux Kernel 做准备。
该笔记将记录:Linux Kernel Module 的开发方法,旨在快速入门,以及常见问题处理方案。
解决方案
Kernel Module 是已编译的二进制程序,直接插入到 Linux Kernle 中运行。
Kernel Module 运行在 RING0 中,在 x86 CPU 中最低且受保护最少的运行级别。这里的代码完全不受检查地运行,但运行速度令人难以置信,并且可以访问系统的所有内容。
准备工作
1)操作系统:虚拟机或独立运行的 Linux 发行版,用于内核代码测试;应避免在当前系统中直接测试内容,否则可能会导致系统崩溃、数据丢失等等问题; 2)编程语言:需要懂得些 C 语言编程;懂得 Linux Shell 命令行等等工具的使用方法;如果懂得硬件知识或汇编语言会更加的有帮助;
安装开发环境
我们使用 Eclipse 作为开发工具,
我们在 Ubuntu 20.04 TLS 中进行开发工作,需要安装如下包:

apt-get install build-essential # 安装编译器、调试器、库、其他工具
# Depends: libc6-dev | libc-dev, gcc (>= 4:9.2), g++ (>= 4:9.2), make, dpkg-dev (>= 1.17.11)
apt-get install linux-headers-`uname -r` # 安装内核头文件

模块开发
第一步、编写代码
lkm_example.c

// 用于模块开发的头文件
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>

// 模块描述信息
MODULE_LICENSE(“GPL”);
MODULE_AUTHOR(“k4nz@d3rm.org”);
MODULE_DESCRIPTION(“A simple example Linux module.”);
MODULE_VERSION(“0.01”);

// 模块初始函数
static int __init lkm_example_init(void) {
printk(KERN_INFO “Hello, World!\n”);
return 0;[……]

READ MORE

「Linux」- 内存管理

物理内存也称为主存,大多数计算机用的主存都是动态随机访问内存(DRAM)。只有内核才可以直接访问物理内存。
内存的分配方式
Buddy Memory Allocation
是最底层的内存管理机制,提供页式的内存管理。
函数调用:alloc_pages()
Slab Allocation
是构建在 Buddy Memory Allocation 上的内存管理,提供基于对象的内存管理。
函数调用: 1)创建对象:kmem_cache_create() 2)分配内存:kmem_cache_alloc() 3)释放内存:kmem_cache_free()
进程如何访问内存
物理内存 与 虚拟内存
Linux 内核给每个进程都提供了一个独立的虚拟地址空间,并且这个地址空间是连续的。这样,进程就可以很方便地访问内存,更确切地说是访问虚拟内存。
并不是所有的虚拟内存都会分配物理内存,只有那些实际使用的虚拟内存才分配物理内存,并且分配后的物理内存,是通过内存映射来管理的。
内存映射
内存映射,其实就是将虚拟内存地址映射到物理内存地址。为了完成内存映射,内核为每个进程都维护了一张页表,记录虚拟地址与物理地址的映射关系。
虚拟内存 =>(虚拟地址)=> 页面表(MMU) => (物理地址)=> 物理内存
对普通进程来说,能看到的其实是内核提供的虚拟内存,这些虚拟内存还需要通过页表,由系统映射为物理内存。
内存管理单元(MMU)
页表实际上存储在处理器的内存管理单元(MMU)中。而当进程访问的虚拟地址在页表中查不到时,系统会产生一个缺页异常,进入内核空间分配物理内存、更新进程页表,最后再返回用户空间,恢复进程的运行。
MMU 以“页”来管理内存,通常是 4 KB 大小,每一次内存映射,都需要关联 4 KB 或者 4KB 整数倍的内存空间。
页的大小只有 4 KB ,导致的另一个问题就是,整个页表会变得非常大。比方说,仅 32 位系统就需要 100 多万个页表项(4GB/4KB),才可以实现整个地址空间的映射。为了解决页表项过多的问题,Linux 提供了两种机制,也就是多级页表和大页(HugePage)。
多级页表就是把内存分成区块来管理,将原来的映射关系改成区块索引和区块内的偏移。由于虚拟内存空间通常只用了很少一部分,那么,多级页表就只保存这些使用中的区块,这样就可以大大地减少页表的项数。Linux 用的正是四级页表来管理内存页,如下图所示,虚拟地址被分为 5 个部分,前 4 个表项用于选择页,而最后一个索引表示页内偏移。

大页(HugePage),顾名思义,就是比普通页更大的内存块,常见的大小有 2MB 和[……]

READ MORE

「Linux」- 缓冲(Buffer)与缓存(Cache)

使用 free 查看查看内存使用情况

# free // 以字节为单位
total used free shared buff/cache available
Mem: 16108680 13563160 301692 731132 2243828 1478772
Swap: 31457276 16751336 14705940

// 1)total,总内存大小;
// 2)used,已使用内存的大小,包含了共享内存;
// 3)free,未使用内存的大小;
// 4)shared,共享内存的大小;
// 5)buff/cache,缓存和缓冲区的大小;
// 6)available,新进程可用内存的大小;包含未使用内存,还包括了可回收的缓存,会比未使用内存更大。但并不是所有缓存都可以回收,因为有些缓存可能正在使用。

命令 free 从 /proc/meminfo 读取数据,根据 man proc 手册:
buffer
1)Buffers,内核缓冲区用到的内存,对应的是 /proc/meminfo 中的 Buffers 值; Buffers,对原始磁盘块的临时存储,也就是用来缓存磁盘的数据,通常不会特别大(20MB 左右)。这样,内核就可以把分散的写集中起来,统一优化磁盘的写入,比如可以把多次小的写合并成单次大的写等等。
cache
2)Cache,内核页缓存和 Slab 用到的内存,对应的是 /proc/meminfo 中的 Cached 与 SReclaimable 之和; Cached,从磁盘读取文件的页缓存,也就是用来缓存从文件读取的数据。 SReclaimable,Slab 的一部分。Slab 包括两部分,其中的可回收部分,用 SReclaimable 记录;而不可回收部分,用 SUnreclaim 记录。
概念理解:Buffer and Cache
Buffer 既可以用作“将要写入磁盘数据的缓存”,也可以用作“从磁盘读取数据的缓存”。Cache 既可以用作“从文件读取数据的页缓存”,也可以用作“写文件的页缓存”。
简单来说,Buffer 是对磁盘数据的缓存,而 Cache 是文件数据的缓存,它们既会用在读请求中,也会用在写请求中。
在读写文件时,会经过文件系统,由文件系统负责与磁盘交互;在读写磁盘时,就会跳过文件系统,也就是所谓的“裸I/O“。这两种读写方式所使用的缓存是不同的,也就是 Cache 和 Buffer 区别。
实验探究:文件写入 与 磁盘写入
写文件时会用到 Cache 缓存数据,而写磁盘则会用到[……]

READ MORE

「Linux」- 内存管理

限制内存的使用
TODO 限制内存的使用(Linux) Restricting process CPU usage using nice, cpulimit, and cgroups
/proc/slabinfo
/proc/meminfo 仅显示 Slab 的整体大小,具体到每一种 Slab 缓存,还要查看 /proc/slabinfo 文件:

$ cat /proc/slabinfo | grep -E ‘^#|dentry|inode’
# name <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : tunables <limit> <batchcount> <sharedfactor> : slabdata <active_slabs> <num_slabs> <sharedavail>
xfs_inode 0 0 960 17 4 : tunables 0 0 0 : slabdata 0 0 0

ext4_inode_cache 32104 34590 1088 15 4 : tunables 0 0 0 : slabdata 2306 2306 0hugetlbfs_inode_cache 13 13 624 13 2 : tunables 0 0 0 : slabdata 1 1 0
sock_inode_cache 1190 1242 704 23 4 : tunables 0 0 0 : slabdata 54 54 0
shmem_inode_cache 1622 2139 712 23 4 : tunables 0 0 0 : slabdata 93 93 0
proc_inode_cache 3560 4080 680 12 2 : tunables 0 0 0 : slabdata 340 340 0
inode_cache 25172 25818 608 13 2 : tunables 0[……]

READ MORE

「Linux」- 检查内存使用情况

问题描述
在服务器中,我们并没有运行太多程序,但是服务器的内存占用很高。
# 03/06/2017 我们还没干什么呢…………有时间再管他吧
# 03/09/2017 后来我们联系机房,技术人员为我们解释出缘由。其实这个问题的答案还是因为我们无知,如果我们在知道的多一点的话就应该知道虚拟化里有个“动态内存”。
这篇文章剩下的内容,主要是介绍在Linux中分析内存使用的方法
方法一、free
查看服务器的内存使用(有关free命令介绍,点击查看):

#!/bin/sh
free -h -w
# total used free shared buffers cache available
# Mem: 3.9G 2.8G 414M 17M 160M 454M 805M
# Swap: 1.0G 9.8M 1.0G

# used = total – free – buffers – cache.: 有点高,我们就是不知道被哪些进程用了。
# shared: 由tmpfs使用的,不高(我们比对了其他三台机器)。
# buffers: 内核缓冲使用的,160M 不高。
# cache:page cache和slabs使用的,454M 也是正常的。
#

先drop_caches看下,(实际并不推荐这么做,因为这么做不是在解决问题,buffer 和 cache 本来都是为了减少IO):

#!/bin/sh
echo 3 > /proc/sys/vm/drop_caches

free -h -w
# total used free shared buffers cache available
# Mem: 3.9G 2.8G 928M 17M 1.5M 103M 879M
# Swap: 1.0G 9.8M 1.0G
# 并没有什么用,只是刷掉 buffer 和 cache 了。这么做也不好,因为buffer 和 cache 本来都是为了减少IO的。

方法二、top
我们用top命令吧(关于top命令的介绍,点击查看)
至于我们的top为什么是这样的,而不是常见的那种,是因为我们的[……]

READ MORE

「Linux」- 内存缓存

# Page Cache 包含磁盘上块映射。
# Inode 表示文件的数据结构
# Dentries 表示目录的数据结构
清除Page Cache缓存:sync; echo 1 > /proc/sys/vm/drop_caches
清除Inode与Dentries缓存:sync; echo 2 > /proc/sys/vm/drop_caches
清除这三者的缓存:sync; echo 3 > /proc/sys/vm/drop_caches
free
可以用 free 或 vmstat,来观察页缓存的大小。free 输出的 Cache,是页缓存和可回收 Slab 缓存的和,
可以从 /proc/meminfo ,直接得到它们的大小:

$ cat /proc/meminfo | grep -E “SReclaimable|Cached”
Cached: 748316 kB
SwapCached: 0 kB
SReclaimable: 179508 kB

参考文献
How to Clear RAM Memory Cache, Buffer and Swap Space on Linux what are pagecache, dentries, inodes?[……]

READ MORE

「Linux」- 内存编辑工具

问题描述
该笔记将记录:在 Linux 中,内存编辑相关的工具,以及相关问题处理。
解决方案
scanmem
https://github.com/scanmem/scanmem
GameConqueror
GameConqueror: scanmem的GUI工具。
Cheat Engine
http://www.cheatengine.org/
在 Windows 和 macOS 中我们能够使用 Cheat Engine 工具。[……]

READ MORE

「Linux」- SWAP(学习笔记)

Swap 说白了就是把一块磁盘空间或者一个本地文件(以磁盘为例),当成内存来使用。它包括换出和换入两个过程: 1)换出,把进程暂时不用的内存数据存储到磁盘中,并释放这些数据占用的内存。 2)换入,在进程再次访问这些内存的时候,把它们从磁盘读到内存中来
现在的内存便宜多,但 SWAP 依旧有用: 1)即使内存不足时,有些应用程序也并不想被 OOM 杀死,而是希望能缓一段时间,等待人工介入,或者等系统自动释放其他进程的内存,再分配给它 2)笔记本电脑的休眠和快速开机的功能,也基于 Swap 。休眠时,把系统的内存存入磁盘,这样等到再次开机时,只要从磁盘中加载内存就可以
在操作系统中,何时发生内存回收
直接内存回收
有新的大块内存分配请求,但是剩余内存不足。此时操作系统就需要回收一部分内存(比如缓存),进而尽可能地满足新内存请求
定期回收内存(kswapd0)
专门的内核线程,kswapd0,用来定期回收内存。
为了衡量内存的使用情况,kswapd0 定义三个内存阈值(watermark,也称为水位),分别是:页最小阈值(pages_min)、页低阈值(pages_low)、页高阈值(pages_high)

pages_free,表示剩余内存: 1)pages_free < pages_min,剩余内存小于页最小阈值,说明进程可用内存基本耗尽,只有内核才可以分配内存 2)pages_min < pages_free < pages_low,内存压力比较大,剩余内存不多,此时 kswapd0 会执行内存回收,直到 pages_free > pages_high 为止 3)pages_low < pages_free < pages_high,内存有一定压力,但还可以满足新内存请求 4)pages_high < pages_free,剩余内存比较多,没有内存压力
参数 pages_min 通过 /proc/sys/vm/min_free_kbytes 设置,pages_low = pages_min*5/4,pages_high = pages_min*3/2
NUMA 与 Swap
有时候可能会发现 Swap 升高,但是系统内存足够。这种情况可能是因为 处理器的 NUMA (Non-Uniform Memory Access) 架构导致的问题。
NUMA – Non-Uniform Memory Access
在 NUMA 架构下,多个处理器(逻辑处理器)被划分到不同 Node 上,且每个 Node 都拥有自己的本地内存空间。
同个 Node 内部的内存空间,实际上又可以进一步分为不同的内存域(Zone),比如直接内存访问区[……]

READ MORE

「Learning Linux Kernel」- 进程

“session leaders” in `ps`
What are “session leaders” in `ps`? CSDN/The Linux Process Principle, PID、PGID、PPID、SID、TID、TTY
在 Linux 中,每个进程都有若干相关的”数值“:
PID,进程号
用于标识进程的任意数值。每个进程都具有唯一的进程号,在进程退出后且父进程检索退出状态后,会释放进程号以留作新进程使用。
PPID,父进程号
启动进程的进程的进程号。
PGID,进程组号
每个进程都属于某个进程组(Process Group),在每个进程组中可以包含多个进程。每个进程组都会有一个领导进程(Process Group Leader),领导进程的进程号为进程组号,以识别进程组。领导进程可以先退出,但是进程组依然存在,并具有相同的进程组号,直到在进程组中的最后一个进程结束。进程组简化进程操作,可以以组为单位进行管理。
SID,会话号
在Shell支持作业控制(Job Control)的前提下,多个进程组还可以构成单个会话。(1)每个会话有单个或多个进程组组成,可以存在单个领头进程,也可以没有。(2)会话领导进程的进程号会识别为会话号。(3)在会话中的进程组称为作业(Job)。(4)会话可以有一个进程组成为会话的前台作业(Foreground Job),而其他的进程组是后台工作(Background Job)。(5)每个会话可以连接一个控制终端(Control Terminal)。当控制终端有输入输出时,都传递给该会话的前台进程组。由终端产生的信号,比如CTRL+Z、CTRL+C等等,会传递到前台进程组。(6)会话的意义在于将多个作业(进程组)囊括在一个终端,并取其中某个作业作为前台,来直接接收该终端的输入输出以及终端信号,其他作业在后台运行。
会话与进程组只是将相关进程作为管理单元的方式。在进程组里的所有成员总是属于相同会话,但是单个会话中可能有多个进程组。
通常,Shell是单个会话领导,由该Shell执行的管道将是进程组。这便于在退出时结束Shell的子进程。
RGID and EGID, PGID and SGID
GID, current, primary, supplementary, effective and real group IDs?
在 Linux 中:(1)每个用户都具有组号,分为主要组号(Primary Group ID)与附属组号(Supplementary Group ID);(2)每个进程具有所属的用户组号,分为实际组号(Real Group ID)与有效组号(Effective Group ID)。这是两个概念:[……]

READ MORE

「Learning Linux Kernel」- 进程管理(学习笔记)

进程 与 线程
进程,是处于执行期的程序,及其他相关资源(比如 打开的文件、挂起的信号、内核内部数据、一个或多个内存地址空间、一个或多个执行线程、存放全局变量的数据段 等等)的总称。进程不仅指正在执行的程序代码。
线程,是执行线程的简称,是在进程中活动的对象。每个线程具有独立的程序计数器(Program Counter)、线程栈、一组进程寄存器。内核调度的对象是线程,而不是进程,但是 Linux 并不特别区分线程与进程,对于 Linux 而言,线程只是一种特殊进程。
现代操作系统为进程提供两种虚拟机制:虚拟处理器与虚拟内存。虚拟处理器,然进程认为自身独占整个处理器。虚拟内存,让进程认为自己独占全部内存。但是,在 Linux 中,线程是共享虚拟内存的,但是每个线程都拥有各自的虚拟处理器。
进程从创建时开始存活。在 Linux 中,进程使用 fork() 系统调用,通过复制现有进程(父进程),来创建新进程(子进程)。在现代 Linux 内核中,fork() 使用 clone() 系统调用来实现。当 fork() 调用结束时,返回调用 fork() 函数的位置,继续执行后续代码,但是会“返回两次”。但实际上并“不是返回两次”,只是看起来“像返回两次”,因为 fork() 通过复制创建子进程,当 fork() 调用结束后,此时系统中会存在两个相同的进程(至少可执行代码是相同的)。在父进程中,fork() 返回子进程的进程 ID。在子进程中,fork 返回 0,表示创建成功。参考 fork() in C 文章,获取说明示例。
在通常情况下,创建进程是为了执行新的程序,而不是单纯的复制自身。因此,在 fork() 调用之后,我们会接着调用 exec() 函数,用于创建新的地址空间,并将新的程序载入其中以执行。
程序使用 exit() 系统调用退出执行,该函数会终结进程并释放资源。父进程可以通过 wait4() 查询子进程是否终结,这使父进程可以等待子进程执行结束。在进程退出后,被设置为僵死状态,直到父进程调用 wait() 或者 waitpid() 为止。
进程描述符 与 任务结构
在内核中,进程列表保存在名为任务队列(Task List)的双向循环链表中。链表的每一项都是 task_struct 结构(在 /include/linux/sched.h 中),包含具体进程的全部信息,被称为进程描述符(Process Descriptor)。
task_struct(进程描述符、Process Descriptor)
进程描述符相对较大,因为其中包含的数据能够完整的描述一个正在执行的程序:打开的文件,进程地址空间,挂起的信号,进程的状态,以及其他信息。
分配进程描述符
在 Linux 2.6[……]

READ MORE

「Linux」- 进程状态(学习笔记)

相关文档及学习资料
Understanding Linux Process States
关于进程状态关系的图解
Understanding Processes on Linux
R Running or runnable (on run queue) 根据 Understanding Linux Process States 描述,进程具有 Running 与 Runnable 状态,但是 p->state = TASK_RUNNING 状态,即状态字段是相同的。
D Uninterruptible sleep (waiting for some event)
S Interruptible sleep (waiting for some event or signal)
T Stopped, either by a job control signal or because it is being traced by a debugger.
t stopped by debugger during the tracing 当使用调试器(如 gdb)调试某个进程时,在使用断点中断进程后,进程就会变成跟踪状态,这其实也是种特殊的暂停状态,只不过可以用调试器来跟踪并按需要控制进程的运行。
Z Zombie process, terminated but not yet reaped by its parent.
I Idle kernel thread 用在不可中断睡眠的内核线程上。硬件交互导致的不可中断进程用 D 表示,但对某些内核线程来说,它们有可能实际上并没有任何负载,用 Idle 正是为了区分这种情况。要注意,D 状态的进程会导致平均负载升高, I 状态的进程却不会。
W paging (not valid since the 2.6.xx kernel)
X dead (should never be seen)
使用命令查看进程当前状态
使用命令 ps l 查看进程状态,显示进程休眠或者运行。如果进程正在休眠,WCHAN 列(wait channel,等待队列的名称)显示进程正在等待的内核事件。

# ps l
F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
0 500 5942 5928 15 0 12916 1460 wait Ss pts/14 0:00 -/bin/bash
0 500 12235 5942 15 0 21004 3572 wait S+ pt[……]

READ MORE

「Learning Linux Kernel」- 进程调度(学习笔记)

进程调度,由进程调度程序负责,它是确保内核能够有效工作的子系统,负责在可运行态进程之间分配有限的处理器时间资源。调度程序决定了哪个进程在哪个时间运行多少时间。调度程序是多任务操作系统的基础。只有通过调度程序的合理调度,系统资源才能最大限度的发挥作用,多进程才会出现并发执行的效果。
调度程序,需要最大限度的利用处理器资源,而原则是:只要有可以执行的进程,那么总会有进程在执行。但是只要系统中可运行进程数比处理器个数多,就注定会有进程不能运行(在等待运行)
调度程序,需要完成的基本工作就是:从在一组可运行状态的进程中选择一个来执行。
多任务(Multitasking)
多任务操作系统,即能同时并发地交互执行多个进程的操作系统。在单处理器上,这会产生多个进程在同时运行的幻觉。在多处理器上,这会使多个进程在不同的处理器上真正同时、并行地运行。
多任务操作系统可以使多个进程处于休眠或阻塞状态,也就是说,实际上进程不被投入运行。这些进程虽然存在于内存中,但并不处于可运行状态,他们被阻塞,直到某一事件发生(比如等待键盘输入、网络响应等等)。因此,在操作系统中,虽然存在很多进程,但不是没一个都处于运行或可运行状态。
多任务操作系统分为两类:非抢占式多任务(cooperative multitasking);抢占式多任务(preemptive multitasking)。

与其他现代操作系统一样,Linux 采用抢占式多任务。在抢占式多任务模式下,由调度程序决定什么时候停止一个进程的运行,以便其他进程可以执行。调度程序强制挂起进程的行为就叫做抢占(preemption)。进程在被抢占前能够运行的时间是预先设置好的,这个时间称为进程时间片(timeslice)。时间片是分配给每个可运行进程的处理器时间段。有效的管理时间片能使调度程序从系统全局的角度作出调度决定,还能避免进程独占系统资源。很多现代操作系统都采用动态时间片计算的方式,并且引入可配置的计算策略。但是,Linux 的公平调度程序没有采用时间片的方式来公平调度。

在非抢占式多任务模式下,需要进程主动挂起自己(该操作称之为让步yielding)。缺点也比较明显:进程不受调度程序控制,所以独占处理器时间可能超过用户预料;如果进程挂起而不让步,系统则可能崩溃。不过,近年来的操作系统都是抢占式多任务。

Linux 的进程调度历史
在 Kernel 2.4 以前,Linux 的调度程序都相当简陋,很容易理解,但是在较多可运行进程或多处理环境下表现不佳。
在 Lernel 2.5 版本,开始采用称为 O(1) 调度程序的新调度程序,由算法的行为而得名。它解决了先前的问题,并引入许多强大的新特性与性能特征。这要[……]

READ MORE

「Linux」- 上下文切换(学习笔记)

概念讲解:上下文切换
多任务操作系统,并不是真的在同时运行,而是操作系统在短时间内轮流执行任务,造成多任务同时运行的错觉。
什么是上下文?
而在每个任务切换前,操作系统需要保存当前任务的状态,并设置下个任务的运行环境:CPU Registers, Program Counter

CPU Registers:是 CPU 内置的容量小、但速度极快的内存;
Program Counter:用来存储 CPU 正在执行的指令位置、或者即将执行的下一条指令位置;

它们都是 CPU 在运行任何任务前,必须的依赖环境,因此也被叫做 CPU 上下文。
什么是上下文切换?
就是先把前个任务的 CPU 上下文(也就是 CPU 寄存器和程序计数器)保存起来,然后加载新任务的上下文到这些寄存器和程序计数器,最后再跳转到程序计数器所指的新位置,运行新任务。
上下文切换的种类
特权模式切换(系统调用)
按照特权等级,把进程的运行空间分为内核空间和用户空间: 1)内核空间,Ring 0 2)用户空间,Ring 3,只能访问受限资源,不能直接访问内存等硬件设备,必须通过系统调用陷入到内核中,才能访问这些特权资源。
进程在用户空间运行时,被称为进程的用户态,而陷入内核空间的时候,被称为进程的内核态。通过系统调用来完成。
CPU 寄存器里原来用户态的指令位置,需要先保存起来。接着,为了执行内核态代码,CPU 寄存器需要更新为内核态指令的新位置。最后才是跳转到内核态运行内核任务。而系统调用结束后,CPU 寄存器需要恢复原来保存的用户态,然后再切换到用户空间,继续运行进程。所以,一次系统调用的过程,其实是发生了两次 CPU 上下文切换。
系统调用过程通常称为特权模式切换,而不是上下文切换。但实际上,系统调用过程中,CPU 的上下文切换还是无法避免的。
进程上下文切换
进程上下文切换,是指从一个进程切换到另一个进程运行。进程是由内核来管理和调度的,进程的切换只能发生在内核态。进程的上下文不仅包括了虚拟内存、栈、全局变量等用户空间的资源,还包括了内核堆栈、寄存器等内核空间的状态。
因此,进程上下文切换就比系统调用时多了一步:在保存当前进程的内核状态和 CPU 寄存器之前,需要先把该进程的虚拟内存、栈等保存下来;而加载了下一进程的内核态后,还需要刷新进程的虚拟内存和用户栈。
在进程上下文切换次数较多的情况下,很容易导致 CPU 将大量时间耗费在寄存器、内核栈以及虚拟内存等资源的保存和恢复上,进而大大缩短了真正运行进程的时间。另外,Linux 通过 TLB(Translation Lookaside Buffer)来管理虚拟内存到物理内存的映射关系。当虚拟内存更新[……]

READ MORE

「Linux」- 处理器使用率(学习笔记)

多任务操作系统,将每个 CPU 的时间划分为很短的时间片,再通过调度器轮流分配给各个任务使用,因此造成多任务同时运行的错觉。
理解概念:节拍率(Timer Interrupt Frequency)
为了维护 CPU 时间,Linux 通过事先定义的节拍率(在内核中表示为 HZ),触发时间中断,并使用全局变量 Jiffies 记录开机以来的节拍数。每发生一次时间中断,Jiffies 的值就加 1。
节拍率 HZ 是内核的可配选项,可以设置为 100、250、1000 等。系统不同,设置不同,通过查询 /boot/config 的 CONFIG_HZ 内核选项来查看它的配置值。
用户空间节拍率
节拍率 HZ 是内核选项,所以用户空间程序并不能直接访问。为了方便用户空间程序,内核还提供了一个用户空间节拍率 USER_HZ,它总是固定为 100,也就是 1/100 秒。这样,用户空间程序并不需要关心内核中 HZ 被设置成了多少,因为它看到的总是固定值 USER_HZ。
统计数据:查看处理器的总体使用率

# cat /proc/stat | grep ^cpu
cpu 11424212 19477670 9071090 783703472 711024 0 796129 0 0 0
cpu0 3497583 4899058 2362550 195054993 232905 0 330682 0 0 0
cpu1 1923176 4857103 2082146 197184640 87422 0 108655 0 0 0
cpu2 2074101 4841395 2245553 196715460 180663 0 216623 0 0 0
cpu3 3929351 4880112 2380840 194748377 210033 0 140168 0 0 0

如上命令,仅获取 CPU 相关的指标,含义如下: 1)cpu,表示的是所有 CPU 的累加 2)cpu0, cpu1, …,表示不同场景下 CPU 的累加节拍数,它的单位是 USER_HZ,也就是 10 ms(1/100 秒)
每个字段的含义可以查看 man proc 手册,它们都是 CPU 使用率相关的重要指标,很多工具使用这些数据。各列含义如下(依序): 01)user, us:代表用户态 CPU 时间,但不包括下面的 nice 时间,但包括 guest 时间 02)nice, ni:低优先级用户态 CPU 时间,也就是进程的 nice 值被调整为 1-19 之间时的 CPU 时间。nice 可取值范围是 -20 到 19,数值越大,优先级反而越低 03)system, sys:代表内核态 CPU 时间 04)idle, id:代表[……]

READ MORE

「Linux」- 平均负载(Load Average)

相关文章及学习资料
Linux Load Averages: Solving the Mystery
概念讲解:系统负载 与 平均负载
当使用 top 或 uptime 命令时,都会输出 load average 字段:

# uptime
23:47:36 up 5 days, 2:13, 5 users, load average: 0.99, 0.66, 0.55

# top
top – 23:47:53 up 5 days, 2:13, 5 users, load average: 1.01, 0.67, 0.55

分别代表系统在前一分钟,五分钟,十五分钟的平均负载。
什么是系统负载?
系统负载展示系统的处理器、磁盘、其他资源的繁忙程度。系统负载是操作系统执行计算工作的度量,以数字形式显示。如果计算机完全空闲,则系统负载为 0。每个等待处理器资源或正在使用处理器资源的进程都会向系统负载加 1 。如果系统负载为 5,则表示由五个进程在使用处理器或者等待处理器资源。(注意,UNIX 系统通常只计算等待处理器的进程,而 Linux 还会计算其他的资源(比如等待磁盘的读写)
系统负载通常没有太大的含义:因为它在这一秒为零,那么下一秒可能为五,因为那时可能有五个进程在等待资源。这也是为什么:在 UNIX 中,显示的是某段时间内的平均负载,而不是系统负载。
什么是平均负载?
平均负载则是系统负载在一段时间内的平均值。平均负载一般是三个值 load average: 0.99, 0.66, 0.55 形式。
在几乎所有类 Unix 系统中,平均负载只计算运行或等待状态的进程,所以被称之为“CPU Load Average”。
在 Linux 中,技术上认为平均负载是内核执行队列中标记为 正在运行的进程(p->state = TASK_RUNNING) 或 不可中断的进程(p->state = TASK_UNINTERRUPTABLE) 的平均值,所以被称之为“System Load Average”。可以简单理解为“平均负载其实就是平均活跃进程数”,它实际上是活跃进程数的指数衰减平均值(使用 EMA 算法)。
输出解读:平均负载具体含义
使用 uptime 命令来查看平均负载,也可以通过 watch -n 1 cat /proc/loadavg 文件系统查看。
如果处理器是单核的
我们以 load average: 1.05, 0.70, 5.09 为例。假如你的处理器是单核的,则表示:

在过去的一分钟:机器平均超载 0.05 个,就是说平均有 0.05 个进程在等待处理器资源;
在过[……]

READ MORE

「Linux」- 进程管理

该部分保存了与操作系统进程、资源使用、负载情况相关的内容,及相关的一些概念。
但不包含命令使用方法相关的内容。
# How to Manage Processes from the Linux Terminal: 10 Commands You Need to Know https://www.howtogeek.com/107217/how-to-manage-processes-from-the-linux-terminal-10-commands-you-need-to-know/ top/htop/ps/pstree/kill/pgrep/pkill/killall/renice/xkill
获取进程命令的绝对路径
How can I know the absolute path of a running process?
TODO 获取进程命令的绝对路径
下面的方法不一定好用,毕竟情况复杂:

ps -auxwe | grep 24466
ls -l /proc/24466/exe

pwdx $pid

Windows – 查看进程打开的文件
Which files are opened by a specific application?[……]

READ MORE

「Linux」- 如何结束进程?

问题描述
起初是为了 systemd 的 service 单元文件中的 ExecStop 指令才整理的这篇文章,后来看 systemd 的文档说执行 stop 时,执行完 ExecStop 指令后,未结束的进程会由 systemd 来结束。
本来没有什么可写的,直接使用 kill(1) 命令来结束进程就可以了。但是,由几个有意思的问题: 1)如何结束一个进程的全部子进程? 2)如何结束一个进程及其子进程? 3)我想结束某个组或某个用户的进程该怎么做?
通常结束一个进程的时候,它的子进程不一定会退出,子进程可能会变成“孤儿进程”:

孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。

所以有的时候,我们就需要结束某个进程以及它的子进程。
我们先从基础的开始吧。
根据进程号,结束进程
在 Linux 中,想要结束一个进程可以直接使用kill(1)命令并指定进程ID(PID)就可以了。比如,我们想要结束PID为3219的进程,只需要执行如下命令:

kill -9 3219
kill -KILL 3219

上面的两个命令是100%完全等价的,只是形式不一样而已,具体参考 kill(1) 手册。唯一需要注意:在 Shell 中,内建的kill命令,参考「注意事项」部分。
根据父进程号,结束子进程
如果想要结束进程所有的子进程的ID,可以使用pkill(1)命令。比如,我们想要结束PID为3219的进程的子进程,只需要执行如下命令:

pkill -KILL -P 3219

该命令可以结束某个进程的全部子进程。
结束进程及其全部子进程
方法一、使用进程组
可以使用kill(1)命令或者pkill(1)命令,配合“进程组”的ID来结束进程。比如进程组的ID为4536如下:

kill -KILL -4536
pkill -KILL -g 4536

注意,这里的“4536”是“进程组”的ID,不是进程ID,不是父进程ID,也不是进程所属组的ID,有一个名词叫做“进程组”(Process Group)。可以用下面的命令来体会组ID(gid)、进程组ID(pgid)及其他ID之间的差异,注意观察各个字段的输出:

ps -o pid,ppid,pgid,gid,sess,cmd -U root

上面的ID分别是进程ID、父进程ID、进程组的ID、进程的组ID、会话、命令。
方法二、使用一点 Shell 命令
但是下面的这条命令应该是一[……]

READ MORE

「Linux」- 限制进程资源

本文介绍如何限制进程资源。
SysV init
以前我们用的是init启动。如果要限制进程资源,可以修改/etc/security/limits.conf文件。
但是呢,我们systemd不吃这个一套。
systemd
在systemd中,如果要限制资源,需要修改/etc/systemd/system.conf与/etc/systemd/system.conf文件。
注意事项,修改/etc/systemd/system.conf后,需要执行systemctl daemon-reexec命令来重新加载配置。
各参数含义
虽然他们读取的配置不会,还存在很多的差异,但是都是使用方式的差异。它们底层控制的资源还是相同的。
下面只是一个概览(有关详细内容及微妙例外情况,强烈建议参考setrlimit(2)手册):

Directive in systemd
Unit in systemd
ulimit equivalent
Description

LimitCPU=
ulimit -t
Seconds
 

LimitCPU=
ulimit -t
Seconds
 

LimitFSIZE=
ulimit -f
Bytes
 

LimitDATA=
ulimit -d
Bytes
 

LimitSTACK=
ulimit -s
Bytes
 

LimitCORE=
ulimit -c
Bytes
 

LimitRSS=
ulimit -m
Bytes
 

LimitNOFILE=
ulimit -n
Number of File Descriptors
文件描述符的个数

LimitAS=
ulimit -v
Bytes
 

LimitNPROC=
ulimit -u
Number of Processes
当前用户允许创建的进程数。如果超过或等于该值,在fork(2)[……]

READ MORE