[转帖]Linux内核源码之Netfilter框架

linux,内核,源码,netfilter,框架 · 浏览次数 : 0

小编点评

排版内容如下: ``` 452013.507230 [MAC_DES:70,f3,95,e,42,faMAC_SRC: 0,f,fe,f6,7c,13 Prot:8][452013.507237] src IP:'10.6.124.55', dst IP:'10.6.124.54' 452013.944960 [MAC_DES:70,f3,95,e,42,faMAC_SRC: 0,f,fe,f6,7c,13 Prot:8][452013.944968] src IP:'10.6.124.55', dst IP:'10.6.124.54' 452014.960934 [MAC_DES:70,f3,95,e,42,faMAC_SRC: 0,f,fe,f6,7c,13 Prot:8][452014.960941] src IP:'10.6.124.55', dst IP:'10.6.124.54' 452015.476335 [MAC_DES:70,f3,95,e,42,faMAC_SRC: 0,f,fe,f6,7c,13 Prot:8][452015.476342] src IP:'10.6.124.55', dst IP:'10.6.124.54' 452016.023311 [MAC_DES:70,f3,95,e,42,faMAC_SRC: 0,f,fe,f6,7c,13 Prot:8][452016.023318] src IP:'10.6.124.55', dst IP:'10.6.124.54' ```

正文

https://zhuanlan.zhihu.com/p/413179209

 

一、概述:Netfilter是什么

对于不经常接触Linux内核的应用层开发者来说,可能对Netfilter了解的比较少。但大多数Linux用户多少都用过或知道iptables,然而,iptables的功能实现就是在Netfilter之上完成的。

Netfilter 框架由著名的Linux开发人员Rusty Russell于1998年开发,旨在改进以前实现ipchains(Linux2.2.x)和ipfwadm(Linux2.0.x)。

Netfilter 是 Linux 内核中的一个框架,它为以定制处理器形式实施的各种网络相关操作提供了灵活性。Netfilter 提供数据包过滤、网络地址翻译和端口翻译的各种选项。

1.Netfilter构成

其详细组成:

Netfilter是 Linux 内核中进行数据包过滤,连接跟踪(Connect Track),网络地址转换(NAT)等功能的主要实现框架;该框架在网络协议栈处理数据包的关键流程中定义了一系列钩子点(Hook 点),并在这些钩子点中注册一系列函数对数据包进行处理。这些注册在钩子点的函数即为设置在网络协议栈内的数据包通行策略,换句话说就是,这些函数可以决定内核是接受还是丢弃某个数据包,函数的处理结果决定网络数据包的“命运”。

从图中我们可以看到,Netfilter 框架采用模块化设计理念,并且贯穿了 Linux 系统的内核态和用户态。

在用户态层面,根据不同的协议类型,为上层用户提供了不同的系统调用工具,比如我们常用的针对IPv4协议iptables,IPv6 协议的ip6tables,针对ARP协议的arptables,针对网桥控制的ebtables,针对网络连接追踪的conntrack等。

不同的用户态工具在内核中有对应的模块进行实现,而底层都需要调用 Netfilter hook API 接口进行实现。

同时也发现,之前提到的iptables,Linux防火墙工具其实也是 Netfilter 框架中的一个组件。

2.Netfilter数据包路径

正常数据包在Netfilter中的路径:

二、Netfilter实现

Netfilter Hooks in the Linux Kernel

1.Netfilter挂载点:Netfilter places

(1)函数定义

从上面网络包发送接受流程图中看出,可以在不同的地方注册 Nefilter 的 hook 函数.由如下定义:

// include/linux/netfilter.h

enum nf_inet_hooks {
        NF_INET_PRE_ROUTING,
        NF_INET_LOCAL_IN,
        NF_INET_FORWARD,
        NF_INET_LOCAL_OUT,
        NF_INET_POST_ROUTING,
        NF_INET_NUMHOOKS
};
  • NF_INET_PRE_ROUTING: incoming packets pass this hook in the () function before they are processed by the routing code. ip_rcv()``linux/net/ipv4/ip_input.c
  • NF_INET_LOCAL_IN: all incoming packets addressed to the local computer pass this hook in the function . ip_local_deliver()
  • NF_INET_FORWARD: incoming packets are passed this hook in the function . ip_forwared()
  • NF_INET_LOCAL_OUT: all outgoing packets created in the local computer pass this hook in the function . ip_build_and_send_pkt()
  • NF_INET_POST_ROUTING: this hook in the ipfinishoutput() function before they leave the computer.

(2)挂载点分析

Netfilter 通过向内核协议栈中不同的位置注册 钩子函数(Hooks) 来对数据包进行过滤或者修改操作,这些位置称为 挂载点,主要有 5 个:PRE_ROUTINGLOCAL_INFORWARDLOCAL_OUT 和 POST_ROUTING

挂载点解析:

  • PRE_ROUTING:路由前。数据包进入IP层后,但还没有对数据包进行路由判定前。
  • LOCAL_IN:进入本地。对数据包进行路由判定后,如果数据包是发送给本地的,在上送数据包给上层协议前。
  • FORWARD:转发。对数据包进行路由判定后,如果数据包不是发送给本地的,在转发数据包出去前。
  • LOCAL_OUT:本地输出。对于输出的数据包,在没有对数据包进行路由判定前。
  • POST_ROUTING:路由后。对于输出的数据包,在对数据包进行路由判定后。

路由判定:

从上图可以看出,路由判定是数据流向的关键点。

  • 第一个路由判定通过查找输入数据包 IP头部 的目的 IP地址 是否为本机的 IP地址,如果是本机的 IP地址,说明数据是发送给本机的。否则说明数据包是发送给其他主机,经过本机只是进行中转。
  • 第二个路由判定根据输出数据包 IP头部 的目的 IP地址 从路由表中查找对应的路由信息,然后根据路由信息获取下一跳主机(或网关)的 IP地址,然后进行数据传输。

数据包流向 从图中可以看到,三个方向的数据包需要经过的钩子节点不完全相同:

发往本地:NF_INET_PRE_ROUTING-->NF_INET_LOCAL_IN

转发:NF_INET_PRE_ROUTING-->NF_INET_FORWARD-->NF_INET_POST_ROUTING

本地发出:NF_INET_LOCAL_OUT-->NF_INET_POST_ROUTING

(3)挂载链表

通过向这些 挂载点 注册钩子函数,就能够对处于不同阶段的数据包进行过滤或者修改操作。由于钩子函数能够注册多个,所以内核使用链表来保存这些钩子函数。当数据包进入本地(LOCAL_IN 挂载点)时,就会相继调用ipt_hook 和 fw_confirm 钩子函数来处理数据包。另外,钩子函数还有优先级,优先级越小越先执行。正因为挂载点是通过链表来存储钩子函数,所以挂载点又被称为 ,挂载点对应的链名称如下所示:

  • LOCAL_IN 挂载点:又称为 INPUT链
  • LOCAL_OUT 挂载点:又称为 OUTPUT链
  • FORWARD 挂载点:又称为 PORWARD链
  • PRE_ROUTING 挂载点:又称为 PREROUTING链
  • POST_ROUTING 挂载点:又称为 POSTOUTING链

Netfilter 定义了 5 个常量来表示这 5 个位置,如下代码:

// 文件:include/linux/netfilter_ipv4.h
#define NF_IP_PRE_ROUTING   0
#define NF_IP_LOCAL_IN      1
#define NF_IP_FORWARD       2
#define NF_IP_LOCAL_OUT     3
#define NF_IP_POST_ROUTING  4

2.注册钩子函数:Register the hooks

注册和解注册钩子函数:Register the hooks

(1)注册和解注册钩子函数

kernel 提供如下函数来注册和解除hook函数.

// include/linux/netfilter.h
/* Function to register/unregister hook points. */

int nf_register_hook(struct nf_hook_ops *reg);
void nf_unregister_hook(struct nf_hook_ops *reg);
int nf_register_hooks(struct nf_hook_ops *reg, unsigned int n);
void nf_unregister_hooks(struct nf_hook_ops *reg, unsigned int n);

这些函数用于将自定义的钩子操作(struct nf_hook_ops)注册到指定的钩子节点中。

(2)钩子操作数据结构

其中结构如下: nf_hook_ops

struct nf_hook_ops
{
        struct list_head list;

        /* User fills in from here down. */
        nf_hookfn *hook;
        struct module *owner;
        u_int8_t pf;
        unsigned int hooknum;
        /* Hooks are ordered in ascending priority. */
        int priority;
};

这个结构体中存储了自定义的钩子函数(nf_hookfn),函数优先级(priority),处理协议类型(pf),钩子函数生效的钩子节点(hooknum)等信息。

(3)注册钩子函数

当定义好一个钩子函数结构后,需要调用 nf_register_hook 函数来将其注册到 nf_hooks 数组中,nf_register_hook 函数的实现如下:

// 文件:net/core/netfilter.c

int nf_register_hook(struct nf_hook_ops *reg)
{    struct list_head *i;
    br_write_lock_bh(BR_NETPROTO_LOCK); 
    // 对 nf_hooks 进行上锁
    // priority 字段表示钩子函数的优先级    
    // 所以通过 priority 字段来找到钩子函数的合适位置    
    
    for (i = nf_hooks[reg->pf][reg->hooknum].next; i != &nf_hooks[reg->pf][reg->hooknum];i = i->next) 
    {
        if (reg->priority < ((struct nf_hook_ops *)i)->priority)
        break;
    }
    list_add(&reg->list, i->prev); // 把钩子函数添加到链表中
    br_write_unlock_bh(BR_NETPROTO_LOCK); // 对 nf_hooks 进行解锁
    return 0;
}

nf_register_hook 函数的实现比较简单,步骤如下:

  • 对 nf_hooks 进行上锁操作,用于保护 nf_hooks 变量不受并发竞争。
  • 通过钩子函数的优先级来找到其在钩子函数链表中的正确位置。
  • 把钩子函数插入到链表中。
  • 对 nf_hooks 进行解锁操作。

3.声明钩子函数:hook functions

其中hook函数由 指定,其函数声明如下: nf_hookfn *hook

// include/linux/netfilter.h

typedef unsigned int nf_hookfn(unsigned int hooknum,
                               struct sk_buff *skb,
                               const struct net_device *in,
                               const struct net_device *out,
                               int (*okfn)(struct sk_buff *));

它返回如下结果之一:

// <linux/netfilter.h>
#define NF_DROP 0
#define NF_ACCEPT 1
#define NF_STOLEN 2
#define NF_QUEUE 3
#define NF_REPEAT 4
#define NF_STOP 5
#define NF_MAX_VERDICT NF_STOP

4.处理协议类型:pf

pf (protocol family) 是协议系列的标识符.

enum {
        NFPROTO_UNSPEC =  0,
        NFPROTO_IPV4   =  2,
        NFPROTO_ARP    =  3,
        NFPROTO_BRIDGE =  7,
        NFPROTO_IPV6   = 10,
        NFPROTO_DECNET = 12,
        NFPROTO_NUMPROTO,
};

5.钩子标识:hooknum

钩子标识符,每个协议系列的所有有效标识符都在头文件中定义。

例如:

<linux/netfilter_ipv4.h>

/* IP Hooks */
/* After promisc drops, checksum checks. */
#define NF_IP_PRE_ROUTING       0
/* If the packet is destined for this box. */
#define NF_IP_LOCAL_IN          1
/* If the packet is destined for another interface. */
#define NF_IP_FORWARD           2
/* Packets coming from a local process. */
#define NF_IP_LOCAL_OUT         3
/* Packets about to hit the wire. */
#define NF_IP_POST_ROUTING      4
#define NF_IP_NUMHOOKS          5

6.钩子优先级:priority

钩子的优先级,每个协议系列的所有有效标识符都在头文件中定义。

例如:
<linux/netfilter_ipv4.h>

enum nf_ip_hook_priorities {
        NF_IP_PRI_FIRST = INT_MIN,
        NF_IP_PRI_CONNTRACK_DEFRAG = -400,
        NF_IP_PRI_RAW = -300,
        NF_IP_PRI_SELINUX_FIRST = -225,
        NF_IP_PRI_CONNTRACK = -200,
        NF_IP_PRI_MANGLE = -150,
        NF_IP_PRI_NAT_DST = -100,
        NF_IP_PRI_FILTER = 0,
        NF_IP_PRI_SECURITY = 50,
        NF_IP_PRI_NAT_SRC = 100,
        NF_IP_PRI_SELINUX_LAST = 225,
        NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX,
        NF_IP_PRI_LAST = INT_MAX,
};

 

enum {
        NFPROTO_UNSPEC =  0,
        NFPROTO_IPV4   =  2,
        NFPROTO_ARP    =  3,
        NFPROTO_BRIDGE =  7,
        NFPROTO_IPV6   = 10,
        NFPROTO_DECNET = 12,
        NFPROTO_NUMPROTO,
};

7.触发调用钩子函数

钩子函数已经被保存到不同的链上,什么时候才会触发调用这些钩子函数来处理数据包?要触发调用某个挂载点上(链)的所有钩子函数,需要使用 NF_HOOK 宏来实现,其定义如下:

// 文件:include/linux/netfilter.h

#define   NF_HOOK(pf, hook, skb, indev, outdev, okfn)  (list_empty(&nf_hooks[(pf)][(hook)]) ? (okfn)(skb) : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn)))

首先介绍一下 NF_HOOK 宏的各个参数的作用:

  • pf:协议类型,就是 nf_hooks 数组的第一个维度,如 IPv4 协议就是 PF_INET
  • hook:要调用哪一条链(挂载点)上的钩子函数,如 NF_IP_PRE_ROUTING
  • indev:接收数据包的设备对象。
  • outdev:发送数据包的设备对象。
  • okfn:当链上的所有钩子函数都处理完成,将会调用此函数继续对数据包进行处理。

而 NF_HOOK 宏的实现也比较简单,首先判断一下钩子函数链表是否为空,如果是空的话,就直接调用 okfn 函数来处理数据包,否则就调用 nf_hook_slow 函数来处理数据包。我们来看看 nf_hook_slow 函数的实现:

// 文件:net/core/netfilter.c

int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
                 struct net_device *indev, struct net_device *outdev,
                 int (*okfn)(struct sk_buff *))
{
    struct list_head *elem;
    unsigned int verdict;
    int ret = 0;

    elem = &nf_hooks[pf][hook]; // 获取要调用的钩子函数链表

    // 遍历钩子函数链表,并且调用钩子函数对数据包进行处理
    verdict = nf_iterate(&nf_hooks[pf][hook], &skb, hook, indev, outdev, &elem, okfn);
    ...
    // 如果处理结果为 NF_ACCEPT, 表示数据包通过所有钩子函数的处理, 那么就调用 okfn 函数继续处理数据包
    // 如果处理结果为 NF_DROP, 表示数据包被拒绝, 应该丢弃此数据包
    switch (verdict) {
    case NF_ACCEPT:
        ret = okfn(skb);
        break;
    case NF_DROP:
        kfree_skb(skb);
        ret = -EPERM;
        break;
    }

    return ret;
}

nf_hook_slow 函数的实现也比较简单,过程如下:

  • 首先调用 nf_iterate 函数来遍历钩子函数链表,并调用链表上的钩子函数来处理数据包。
  • 如果处理结果为 NF_ACCEPT,表示数据包通过所有钩子函数的处理, 那么就调用 okfn 函数继续处理数据包。
  • 如果处理结果为 NF_DROP,表示数据包没有通过钩子函数的处理,应该丢弃此数据包。

既然 Netfilter 是通过调用 NF_HOOK 宏来调用钩子函数链表上的钩子函数,那么内核在什么地方调用这个宏呢?

比如数据包进入 IPv4 协议层的处理函数 ip_rcv 函数中就调用了 NF_HOOK 宏来处理数据包,代码如下:

// 文件:net/ipv4/ip_input.c

int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
{
    ...
    return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL, ip_rcv_finish);
}

如上代码所示,在 ip_rcv 函数中调用了 NF_HOOK 宏来处理输入的数据包,其调用的钩子函数链(挂载点)为 NF_IP_PRE_ROUTING。而 okfn 设置为 ip_rcv_finish,也就是说,当 NF_IP_PRE_ROUTING 链上的所有钩子函数都成功对数据包进行处理后,将会调用 ip_rcv_finish 函数来继续对数据包进行处理。

三、Netfilter应用案例

如下为在网络上找到的一个内核模块 Demo,该模块的基本功能是将经过 IPv4 网络层 NF_INET_LOCAL_IN 节点的数据包的源 Mac 地址,目的 Mac 地址以及源 IP,目的 IP 打印出来,源码包下载.NF_INET_LOCAL_IN

代码如下所示:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <linux/tcp.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>


MODULE_LICENSE("GPLv3");
MODULE_AUTHOR("SHI");
MODULE_DESCRIPTION("Netfliter test");

static unsigned int
nf_test_in_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in,
                const struct net_device *out, int (*okfn)(struct sk_buff*));

static struct nf_hook_ops nf_test_ops[] __read_mostly = {
  {
    .hook = nf_test_in_hook,
    .owner = THIS_MODULE,
    .pf = NFPROTO_IPV4,
    .hooknum = NF_INET_LOCAL_IN,
    .priority = NF_IP_PRI_FIRST,
  },
};

void hdr_dump(struct ethhdr *ehdr) {
    printk("[MAC_DES:%x,%x,%x,%x,%x,%x" 
           "MAC_SRC: %x,%x,%x,%x,%x,%x Prot:%x]\n",
           ehdr->h_dest[0],ehdr->h_dest[1],ehdr->h_dest[2],ehdr->h_dest[3],
           ehdr->h_dest[4],ehdr->h_dest[5],ehdr->h_source[0],ehdr->h_source[1],
           ehdr->h_source[2],ehdr->h_source[3],ehdr->h_source[4],
           ehdr->h_source[5],ehdr->h_proto);
}

#define NIPQUAD(addr) \
        ((unsigned char *)&addr)[0], \
        ((unsigned char *)&addr)[1], \
        ((unsigned char *)&addr)[2], \
        ((unsigned char *)&addr)[3]
#define NIPQUAD_FMT "%u.%u.%u.%u"

static unsigned int
nf_test_in_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in,
                const struct net_device *out, int (*okfn)(struct sk_buff*)) {
  struct ethhdr *eth_header;
  struct iphdr *ip_header;
  eth_header = (struct ethhdr *)(skb_mac_header(skb));
  ip_header = (struct iphdr *)(skb_network_header(skb));
  hdr_dump(eth_header);
  printk("src IP:'"NIPQUAD_FMT"', dst IP:'"NIPQUAD_FMT"' \n",
         NIPQUAD(ip_header->saddr), NIPQUAD(ip_header->daddr));
  return NF_ACCEPT;
}

static int __init init_nf_test(void) {
  int ret;
  ret = nf_register_hooks(nf_test_ops, ARRAY_SIZE(nf_test_ops));
  if (ret < 0) {
    printk("register nf hook fail\n");
    return ret;
  }
  printk(KERN_NOTICE "register nf test hook\n");
  return 0;
}

static void __exit exit_nf_test(void) {
  nf_unregister_hooks(nf_test_ops, ARRAY_SIZE(nf_test_ops));
}

module_init(init_nf_test);
module_exit(exit_nf_test);

dmesg | tail 后的结果:

[452013.507230] [MAC_DES:70,f3,95,e,42,faMAC_SRC: 0,f,fe,f6,7c,13 Prot:8]
[452013.507237] src IP:'10.6.124.55', dst IP:'10.6.124.54' 
[452013.944960] [MAC_DES:70,f3,95,e,42,faMAC_SRC: 0,f,fe,f6,7c,13 Prot:8]
[452013.944968] src IP:'10.6.124.55', dst IP:'10.6.124.54' 
[452014.960934] [MAC_DES:70,f3,95,e,42,faMAC_SRC: 0,f,fe,f6,7c,13 Prot:8]
[452014.960941] src IP:'10.6.124.55', dst IP:'10.6.124.54' 
[452015.476335] [MAC_DES:70,f3,95,e,42,faMAC_SRC: 0,f,fe,f6,7c,13 Prot:8]
[452015.476342] src IP:'10.6.124.55', dst IP:'10.6.124.54' 
[452016.023311] [MAC_DES:70,f3,95,e,42,faMAC_SRC: 0,f,fe,f6,7c,13 Prot:8]
[452016.023318] src IP:'10.6.124.55', dst IP:'10.6.124.54'

这个 Demo 程序是个内核模块,模块入口为module_init传入的init_nf_test函数。

在init_nf_test函数中,其通过 Netfilter 提供的 nf_register_hooks 接口将自定义的nf_test_opt注册到钩子节点中。nf_test_opt为struct nf_hook_ops类型的结构体数组,其内部包含了所有关键元素,比如钩子函数的注册节点(此处为NF_INET_LOCAL_IN)以及钩子函数(nf_test_in_hook)。

在nf_test_in_hook函数内部,其检查每一个传递过来的数据包,并将其源 Mac 地址,目的 Mac 地址,源 IP 地址以及目的 IP 地址打印出来。最后返回NF_ACCEPT,将数据包交给下一个钩子函数处理。

与[转帖]Linux内核源码之Netfilter框架相似的内容:

[转帖]Linux内核源码之Netfilter框架

https://zhuanlan.zhihu.com/p/413179209 一、概述:Netfilter是什么 对于不经常接触Linux内核的应用层开发者来说,可能对Netfilter了解的比较少。但大多数Linux用户多少都用过或知道iptables,然而,iptables的功能实现就是在Net

[转帖]【Linux Kernel】学习预热

https://blog.yelvlab.cn/archives/614/ Linux Kernel基础知识 Kernel组成: Linux内核主要由 进程管理、内存管理、设备驱动、文件系统、网络协议栈 外加一个 系统调用。 Kernel源码组织结构 Kernel知识体系 最后修改:2021 年 0

[转帖]linux中 vm.overcommit_memory 的含义

https://www.cnblogs.com/wshenjin/p/15500202.html vm.overcommit_memory 表示内核在分配内存时候做检查的方式。这个变量可以取到0,1,2三个值。对取不同的值时的处理方式都定义在内核源码 mm/mmap.c 的 __vm_enough_

[转帖]探索惊群 ③ - nginx 惊群现象

https://wenfh2020.com/2021/09/29/nginx-thundering-herd/ nginx kernel 本文将通过测试,重现 nginx(1.20.1) 的惊群现象,并深入 Linux (5.0.1) 内核源码,剖析惊群原因。 1. nginx 惊群现象 2. 原因

[转帖]Linux 内核的 Makefile

https://www.cnblogs.com/chenyuting/p/10773313.html Linux内核的配置系统的基本结构 Linux内核的配置系统由三个部分组成,分别是: 1、Makefile:分布在 Linux 内核源代码根目录及各层目录中,定义 Linux 内核的编译规则; 2、

[转帖]Linux内核——netfilter 理解

https://zhuanlan.zhihu.com/p/486271896 目录 收起 Netfilter概述 主要源代码文件 具体功能模块 Netfilter实现 NF_IP_PRE_ROUTING (0) NF_IP_LOCAL_IN (1) NF_IP_FORWARD (2) NF_IP_L

[转帖]Linux内核参数net.ipv4.ip_local_port_range对服务器连接数影响的正确解释

首先明确一下该参数的意义:net.ipv4.ip_local_port_range表示本机作为客户端对外发起tcp/udp连接时所能使用的临时端口范围。 对于TCP连接,本机所能发起的tcp连接数受四元组(源地址*源端口*目标地址*目标端口)限制。 而对于UDP连接,本机所能发起的udp连接数则受二

[转帖]Linux内核网络协议知识补充

https://zhuanlan.zhihu.com/p/597798185 1. 什么是连接?什么情况下算建立了连接? 通过三次握手, 建立连接. 并且源和目的分配了相应资源(缓存等). 2. 什么是心跳? 建立了连接, 很长时间未发送数据包, 连接本身仍是有效的 但存在不可抗力(网线断了), 系

[转帖]Docker资源(CPU/内存/磁盘IO/GPU)限制与分配指南

https://zhuanlan.zhihu.com/p/417472115 什么是cgroup? cgroups其名称源自控制组群(control groups)的简写,是Linux内核的一个功能,用来限制、控制与分离一个进程组(如CPU、内存、磁盘输入输出等)。 什么是Docker资源限制? 默

[转帖]lordrunner监控linux服务器资源情况

https://www.jianshu.com/p/42ff466ea01e 1、首先更新yum源repo 文件是 Linux 中yum源(软件仓库)的配置文件,通常一个 repo 文件定义了一个或者多个软件仓库的细节内容,例如我们将从哪里下载需要安装或者升级的软件包,repo文件中的设置内容将被y