Linux kernel Namespace源码分析

本文详述了Linux Kernel的Namespace机制,从task_struct结构开始,探讨了uts_namespace、ipc_namespace、mnt_namespace、pid_namespace和net_namespace。通过分析kernel、Namespace与Process的关系,以及在创建Namespace时的流程,如copy_process、copy_namespaces等关键步骤,帮助读者理解Docker容器的Namespace隔离原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

学习一下linux kernel namespace的代码还是很有必要的,让你对docker容器的namespace隔离有更深的认识。我的源码分析,是基于Linux Kernel 4.4.19 (https://www.kernel.org/pub/linux/kernel/v4.x/patch-4.4.19.gz)版本的,由于namespace模块更新很少,因此其他相近版本之间雷同。User namespace由于与其他namespaces耦合在一起,比较难分析,我将在后续再作分析。

Kernel,Namespace,Process

Linux Namespace是一种Linux Kernel提供的资源隔离方案,提供Pid,Network,Ipc,Uts,Mount等资源的隔离,每个Namespace下的这些资源对于其他Namespace是不可见的。
注意,一个进程可以同时属于多个Namespace。Linux Kernel、Namespace、Process之间的关系可以用下图描述。
这里写图片描述

Begin with “task_struct”

As u know, Linux Namespace是用来做进程资源隔离的,那么在进程描述符中,一定有对应的Namespaces Info。
在linux-4.4.19/include/linux/sched.h #1380 定义task_struct结构体,该结构体是Linux Process完整信息的集合,其中就包含了一个指向Namespace结构体的指针nsproxy。

struct task_struct {
      ...
      /* namespaces */
      struct nsproxy *nsproxy;
      ...
}

nsproxy结构体的定义在linux-4.4.6/include/linux/nsproxy.h #29

/*
 * A structure to contain pointers to all per-process
 * namespaces - fs (mount), uts, network, sysvipc, etc.
 *
 * The pid namespace is an exception -- it's accessed using
 * task_active_pid_ns.  The pid namespace here is the
 * namespace that children will use.
 *
 * 'count' is the number of tasks holding a reference.
 * The count for each namespace, then, will be the number
 * of nsproxies pointing to it, not the number of tasks.
 *
 * The nsproxy is shared by tasks which share all namespaces.
 * As soon as a single namespace is cloned or unshared, the
 * nsproxy is copied.
 */
struct nsproxy {
      atomic_t count;
      struct uts_namespace *uts_ns;
      struct ipc_namespace *ipc_ns;
      struct mnt_namespace *mnt_ns;
      struct pid_namespace *pid_ns_for_children;
      struct net         *net_ns;
};

注意:正如如上代码注释写到,只要namespace被clone了,那么nsproxy就会跟着被clone。
同时,nsproxy.h中定义了一些对namespace的操作,包括copy_namespaces等。

 int copy_namespaces(unsigned long flags, struct task_struct *tsk);
void exit_task_namespaces(struct task_struct *tsk);
void switch_task_namespaces(struct task_struct *tsk, struct nsproxy *new);
void free_nsproxy(struct nsproxy *ns);
int unshare_nsproxy_namespaces(unsigned long, struct nsproxy **, struct cred *, struct fs_struct *);
int __init nsproxy_cache_init(void);
static inline void put_nsproxy(struct nsproxy *ns) { … }
static inline void get_nsproxy(struct nsproxy *ns) { … }

uts_namespace

linux-4.4.19/include/linux/utsname.h #12

struct uts_namespace {
       struct kref kref;
       struct new_utsname name;
       struct user_namespace *user_ns;
       struct ns_common ns;
};

ipc_namespace

linux-4.4.19/include/linux/ipc_namespace.h #21

struct ipc_namespace {
       atomic_t      count;
       struct ipc_ids      ids[3];


       int          sem_ctls[4];
       int          used_sems;


       unsigned int msg_ctlmax;
       unsigned int msg_ctlmnb;
       unsigned int msg_ctlmni;
       atomic_t      msg_bytes;
       atomic_t      msg_hdrs;


       size_t           shm_ctlmax;
       size_t           shm_ctlall;
       unsigned long     shm_tot;
       int          shm_ctlmni;
       /*
        * Defines whether IPC_RMID is forced for _all_ shm segments regardless
        * of shmctl()
        */
       int          shm_rmid_forced;


       struct notifier_block ipcns_nb;


       /* The kern_mount of the mqueuefs sb.  We take a ref on it */
       struct vfsmount  *mq_mnt;


       /* # queues in this ns, protected by mq_lock */
       unsigned int    mq_queues_count;


       /* next fields are set through sysctl */
       unsigned int    mq_queues_max;   /* initialized to DFLT_QUEUESMAX */
       unsigned int    mq_msg_max;      /* initialized to DFLT_MSGMAX */
       unsigned int    mq_msgsize_max;  /* initialized to DFLT_MSGSIZEMAX */
       unsigned int    mq_msg_default;
       unsigned int    mq_msgsize_default;


       /* user_ns which owns the ipc ns */
       struct user_namespace *user_ns;


       struct ns_common ns;
};

mnt_namespace

linux-4.4.19/fs/mount.h #7

struct mnt_namespace {
       atomic_t             count;
       struct ns_common     ns;
       struct mount *    root;
       struct list_head   list;
       struct user_namespace    *user_ns;
       u64               seq; /* Sequence number to prevent loops */
       wait_queue_head_t poll;
       u64 event;
};

pid_namespace

linux-4.4.19/include/linux/pid_namespace.h #24

struct pid_namespace {
       struct kref kref;
       struct pidmap pidmap[PIDMAP_ENTRIES];
       struct rcu_head rcu;
       int last_pid;
       unsigned int nr_hashed;
       struct task_struct *child_reaper;
       struct kmem_cache *pid_cachep;
       unsigned int level;
       struct pid_namespace *parent;
#ifdef CONFIG_PROC_FS
       struct vfsmount *proc_mnt;
       struct dentry *proc_self;
       struct dentry *proc_thread_self;
#endif
#ifdef CONFIG_BSD_PROCESS_ACCT
       struct fs_pin *bacct;
#endif
       struct user_namespace *user_ns;
       struct work_struct proc_work;
       kgid_t pid_gid;
       int hide_pid;
       int reboot;    /* group exit code if this pidns was rebooted */
       struct ns_common ns;
};

net_namespace

linux-4.4.19/include/net/net_namespace.h #47

struct net {
       atomic_t             passive; /* To decided when the network
                                           * namespace should be freed.
                                           */
       atomic_t             count;           /* To decided when the network
                                           *  namespace should be shut down.
                                           */
       spinlock_t            rules_mod_lock;


       atomic64_t         cookie_gen;


       struct list_head   list;        /* list of netw
<think>嗯,用户让我介绍一下Linux内核,我需要先理清楚要讲哪些方面。首先得明确Linux内核是什么,是操作系统的核心部分对吧。然后可能需要讲讲它的历史和起源,比如Linus Torvalds在1991年开发的那个项目。接下来应该解释内核的主要功能,比如进程管理、内存管理、设备驱动等等。 然后,可能用户想知道架构设计,比如它属于类Unix系统,但和Unix的具体区别在哪里。还有内核的模块化设计,动态加载模块这个特点很重要。另外,内核的不同版本类型,比如稳定版、长期支持版这些,用户可能不太清楚,需要说明一下。 开源特性也是重点,GPL协议的意义,社区协作的开发模式。应用场景方面,服务器、嵌入式系统、Android这些例子比较典型。可能还需要提到安全性和性能优化,但不用太深入,保持概述级别。 要注意避免使用太多技术术语,用通俗易懂的中文解释。还要检查结构是否清晰,分点分段是否合适。是否需要举例子帮助理解?比如进程调度如何工作,或者内存管理的作用。可能用户是初学者,所以需要保持简洁明了,同时覆盖关键点。 另外,用户可能对内核和操作系统的区别有疑问,要明确内核是操作系统的一部分,负责核心功能,而其他部分如用户界面、应用程序属于用户空间。最后是否需要推荐学习资源或进一步的方向?可能对用户有帮助,但根据问题本身,可能不需要,保持回答紧扣主题即可。 确保使用正确的LaTeX格式,行内公式用$...$,独立公式单独成段。不过这个问题可能不太需要数学公式,但如果有涉及性能指标或算法,可能需要简单提及。不过根据问题,可能不需要,所以暂时不用考虑公式部分。 最后检查语言是否流畅,是否符合中文表达习惯,有没有遗漏重要信息。比如是否提到实时性补丁(如PREEMPT_RT),或者容器技术如Docker对内核的影响?可能属于进阶内容,概述中点到为止即可。总之,要全面而简洁地介绍Linux内核,覆盖定义、历史、功能、架构、版本、开源、应用等方面。</think>Linux 内核是操作系统的核心组件,负责管理硬件资源、提供基础服务并协调用户程序与硬件之间的交互。以下是其关键特性的分步解析: 1. **基础定义** - 位于操作系统底层,遵循**单体式内核架构**(Monolithic Kernel) - 采用**模块化设计**(Loadable Kernel Modules,LKM),支持动态加载/卸载功能 - 通过系统调用(如 `syscall`)提供用户空间接口 2. **历史演进** - 1991年由 Linus Torvalds 基于 MINIX 系统开发 - 采用 GPLv2 许可证($GPL \geq 2$) - 版本号遵循 `主版本.次版本.修订号` 体系,如 `6.9.0` 3. **核心子系统** | 子系统 | 功能描述 | |----------------|-------------------------------------------------------------------------| | 进程调度 | 使用 CFS(完全公平调度器),时间复杂度 $O(1)$ 的调度算法 | | 内存管理 | 实现虚拟内存(VM)、NUMA 优化,页表管理采用多级结构(x86_64使用4级页表) | | 文件系统 | 支持 ext4/Btrfs/XFS 等,通过 VFS(虚拟文件系统)抽象层统一接口 | | 设备驱动 | 包含 60% 以上的内核代码,遵循统一设备模型(UDM) | | 网络协议栈 | 实现 TCP/IP 协议栈,支持从 L2(数据链路层)到 L7(应用层)的处理 | 4. **关键技术特性** ```c // 示例:内核链表实现(include/linux/list.h) struct list_head { struct list_head *next, *prev; }; ``` - 实时性扩展(PREEMPT_RT 补丁) - 容器支持(cgroups/namespace) - 安全机制(SELinux/AppArmor) 5. **性能指标** - 上下文切换延迟:通常 < 10μs(x86_64) - 中断响应时间:实时内核可达到 μs 级 - 最大进程数:由 `pid_max` 参数控制(默认 32768) 6. **应用场景** - 服务器领域(90% 的公有云使用 Linux 内核) - 嵌入式系统(Android 内核基于 Linux 4.19 LTS) - 超级计算机(TOP500 全部采用 Linux) 建议学习路径:从内核源码目录结构(`arch/`, `drivers/`, `fs/` 等)入手,配合 `procfs`(`/proc`) 和 `sysfs`(`/sys`) 进行实时状态观测。推荐使用 `ftrace` 或 `perf` 工具进行性能分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值