百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

Linux 进程解析(6):资源隔离 (Namespace、Cgroups 与容器化)

myzbx 2025-09-18 23:45 47 浏览

0.简介

在前面文章中,我们对于进程相关的知识和实际案例进行了介绍,但在进程管理的世界中,仅仅理解进程的创建和调度还是不够的。当应用从单机走向容器化,从本地使用走向云端部署,资源隔离的失效轻则导致服务异常,重则导致宕机。本文将对内核级进程隔离和资源限制的实现和使用进行介绍,带读者一起深入理解容器技术的实现。

1.Namespace

Namespace本质上是对于进程可见全局资源的一层封装,使得每一个进程(进程组)都认为自己独占一套独立的资源,其提供了多种类型的Namespace来隔离不同的系统资源:

PID  │ 进程ID隔离      → 容器内首个进程以为自己是"init"(PID=1)  
NET  │ 网络栈隔离      → 容器拥有独立IP、端口、路由表  
IPC  │ 进程通信隔离    → 禁止跨容器的共享内存通信  
MNT  │ 文件系统隔离    → `/` 在容器内外看到不同内容  
UTS  │ 主机名隔离      → 容器可自定义hostname  
USER │ 用户权限隔离    → 容器内"root"≠宿主机root  

NameSpace的核心数据结构是nsproxy,每个进程的task_struct中都有一个nsproxy的指针,指向其所属的命名空间:

struct nsproxy {
    atomic_t count;
    struct uts_namespace *uts;    // UTS Namespace(主机名/域名)
    struct ipc_namespace *ipc;    // IPC Namespace(进程间通信)
    struct mnt_namespace *mnt;    // Mount Namespace(文件系统挂载)
    struct pid_namespace *pid;    // PID Namespace(进程ID)
    struct net           *net;    // Network Namespace(网络资源)
    ...                           //time相关
    struct cgroup_namespace *cgroup; // CGroup Namespace(cgroup视图)
};


struct task_struct {
    // ... 其他字段 ...
    struct nsproxy *nsproxy;  // 进程所属的namespace集合
    // ... 其他字段 ...
};

我们以创建一个新的PID Namespace为例,可以调用clone(CLONE_NEWPID | ...)创建新 PID Namespace,然后会将创建的task指向新的nsproxy。

我们来实际操作一下,使用unshare(用于在新的命名空间中来运行程序)来作为例子,可以看到使用这个之后只能看到bash和ps -ef本身,看不到原本的宿主进程了。

# 创建一个"看不见"宿主进程的隔离环境,--mount-proc让容器挂载独立的/proc,使ps只能看到"假"的进程树
sudo unshare --pid --fork --mount-proc /bin/bash
ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 20:10 pts/3    00:00:00 /bin/bash
root         8     1  0 20:10 pts/3    00:00:00 ps -ef

容器的各种隔离就是通过这种方式来进行实现的,我们的程序需要这个隔离时也可以自己使用这种方法或者函数去进行环境隔离。

2.CGroup

有了Namespace后,容器可以拥有自己的运行环境,但是如果一个容器无限制的去消耗系统资源(CPU,内存等),就可能将整个机器拖垮,所以就需要一种限制手段,也就是CGroup,CGroup(Control Group)是将进程分组并且对每组资源进行监控和限制的一种手段。

CGroup的核心概念有两个:

1)控制组:是一组进程的集合,可以是树状的(子进程继承父进程的限制)。

2)子系统:每个子系统对应一种资源控制,如CPU、内存、IO等。

在linux中,实现CGroup的核心结构是cgroup,其结构主要内容如下,在task_struct中有进程所属的cgroup:

struct cgroup {
    struct cgroup_subsys_state self;
    unsigned long flags;  
    int level;  // 当前cgroup在树中的深度(root=0)
    /* Maximum allowed descent tree depth */
    int max_depth;  // 允许的最大子树深度
    
    ...
    struct kernfs_node *kn;     /* cgroup kernfs entry */
    struct cgroup_file procs_file;  /* handle for "cgroup.procs" */
    struct cgroup_file events_file; /* handle for "cgroup.events" */
 
    ...
    //子系统状态指针
    struct cgroup_subsys_state __rcu *subsys[CGROUP_SUBSYS_COUNT];
    struct cgroup_root *root;
 
    struct list_head cset_links;
  
    struct list_head e_csets[CGROUP_SUBSYS_COUNT];
    
    struct cgroup *dom_cgrp;
    struct cgroup *old_dom_cgrp;        /* used while enabling threaded */
    //CPU统计量
    struct cgroup_rstat_cpu __percpu *rstat_cpu;
    struct list_head rstat_css_list;
    /* cgroup basic resource statistics */
    struct cgroup_base_stat last_bstat;
    struct cgroup_base_stat bstat;
    struct prev_cputime prev_cputime;   /* for printing out cputime */
    struct list_head pidlists;
    struct mutex pidlist_mutex;
    /* used to wait for offlining of csses */
    wait_queue_head_t offline_waitq;
    /* used to schedule release agent */
    struct work_struct release_agent_work;
    /* used to track pressure stalls */
    struct psi_group psi;
    /* used to store eBPF programs */
    struct cgroup_bpf bpf;
    /* If there is block congestion on this cgroup. */
    atomic_t congestion_count;
    /* Used to store internal freezer state */
    struct cgroup_freezer_state freezer;
    // 祖先cgroup的ID数组(快速判断层级关系)
    u64 ancestor_ids[];
};


struct task_struct {
    // ... 其他字段 ...
    struct css_set *cgroups;  // 进程所属的cgroup集合
    // ... 其他字段 ...
};

接下来来看其资源限制的实现逻辑,以CPU限制为例(cpu 子系统通过 cpu.cfs_quota_us 和 cpu.cfs_period_us 控制 CPU 时间片(如 quota=50000、period=100000 表示 50% 使用率)。其整体设置后逻辑如下:

其可以通过如下方式使用限制:

# 创建内存限制组
mkdir /sys/fs/cgroup/memory/mygroup
echo 104857600 > /sys/fs/cgroup/memory/mygroup/memory.limit_in_bytes  # 限制100MB

各类容器(如Docker)中的资源限制也是通过Cgroup来实现的,各类子系统都支持限制,种类较多,不在此列举。

3.总结

Namespace实现了各类,为容器创建独立的运行环境(像网络,进程,文件等),实现了逻辑隔离;CGroup实现了资源控制(CPU、IO等),实现了物理控制,保证系统的稳定和公平。从这个设计也能体会到Linux的分层抽象、按需组合的设计思想。最后用伪代码来启动一个我们自己的容器(主要步骤描述)。

unshare(CLONE_NEWPID | CLONE_NEWNS)  # 创建Namespace
cgroup = Cgroup(cpu_shares=512, memory_limit="1G")  # 创建Cgroup
pivot_root("./alpine-rootfs")  # 切换根文件系统
execv("/bin/bash")  # 启动容器进程




相关推荐

如何设计一个优秀的电子商务产品详情页

加入人人都是产品经理【起点学院】产品经理实战训练营,BAT产品总监手把手带你学产品电子商务网站的产品详情页面无疑是设计师和开发人员关注的最重要的网页之一。产品详情页面是客户作出“加入购物车”决定的页面...

怎么在JS中使用Ajax进行异步请求?

大家好,今天我来分享一项JavaScript的实战技巧,即如何在JS中使用Ajax进行异步请求,让你的网页速度瞬间提升。Ajax是一种在不刷新整个网页的情况下与服务器进行数据交互的技术,可以实现异步加...

中小企业如何组建,管理团队_中小企业应当如何开展组织结构设计变革

前言写了太多关于产品的东西觉得应该换换口味.从码农到架构师,从前端到平面再到UI、UE,最后走向了产品这条不归路,其实以前一直再给你们讲.产品经理跟项目经理区别没有特别大,两个岗位之间有很...

前端监控 SDK 开发分享_前端监控系统 开源

一、前言随着前端的发展和被重视,慢慢的行业内对于前端监控系统的重视程度也在增加。这里不对为什么需要监控再做解释。那我们先直接说说需求。对于中小型公司来说,可以直接使用三方的监控,比如自己搭建一套免费的...

Ajax 会被 fetch 取代吗?Axios 怎么办?

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!今天给大家带来的主题是ajax、fetch...

前端面试题《AJAX》_前端面试ajax考点汇总

1.什么是ajax?ajax作用是什么?AJAX=异步JavaScript和XML。AJAX是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,AJAX可以使网页实...

Ajax 详细介绍_ajax

1、ajax是什么?asynchronousjavascriptandxml:异步的javascript和xml。ajax是用来改善用户体验的一种技术,其本质是利用浏览器内置的一个特殊的...

6款可替代dreamweaver的工具_替代powerdesigner的工具

dreamweaver对一个web前端工作者来说,再熟悉不过了,像我07年接触web前端开发就是用的dreamweaver,一直用到现在,身边的朋友有跟我推荐过各种更好用的可替代dreamweaver...

我敢保证,全网没有再比这更详细的Java知识点总结了,送你啊

接下来你看到的将是全网最详细的Java知识点总结,全文分为三大部分:Java基础、Java框架、Java+云数据小编将为大家仔细讲解每大部分里面的详细知识点,别眨眼,从小白到大佬、零基础到精通,你绝...

福斯《死侍》发布新剧照 "小贱贱"韦德被改造前造型曝光

时光网讯福斯出品的科幻片《死侍》今天发布新剧照,其中一张是较为罕见的死侍在被改造之前的剧照,其余两张剧照都是死侍在执行任务中的状态。据外媒推测,片方此时发布剧照,预计是为了给不久之后影片发布首款正式预...

2021年超详细的java学习路线总结—纯干货分享

本文整理了java开发的学习路线和相关的学习资源,非常适合零基础入门java的同学,希望大家在学习的时候,能够节省时间。纯干货,良心推荐!第一阶段:Java基础重点知识点:数据类型、核心语法、面向对象...

不用海淘,真黑五来到你身边:亚马逊15件热卖爆款推荐!

Fujifilm富士instaxMini8小黄人拍立得相机(黄色/蓝色)扫二维码进入购物页面黑五是入手一个轻巧可爱的拍立得相机的好时机,此款是mini8的小黄人特别版,除了颜色涂装成小黄人...

2025 年 Python 爬虫四大前沿技术:从异步到 AI

作为互联网大厂的后端Python爬虫开发,你是否也曾遇到过这些痛点:面对海量目标URL,单线程爬虫爬取一周还没完成任务;动态渲染的SPA页面,requests库返回的全是空白代码;好不容易...

最贱超级英雄《死侍》来了!_死侍超燃

死侍Deadpool(2016)导演:蒂姆·米勒编剧:略特·里斯/保罗·沃尼克主演:瑞恩·雷诺兹/莫蕾娜·巴卡林/吉娜·卡拉诺/艾德·斯克林/T·J·米勒类型:动作/...

停止javascript的ajax请求,取消axios请求,取消reactfetch请求

一、Ajax原生里可以通过XMLHttpRequest对象上的abort方法来中断ajax。注意abort方法不能阻止向服务器发送请求,只能停止当前ajax请求。停止javascript的ajax请求...