Linux ipcns_notify ipc命名空间变更与sysctl接口ipc_namespace是Linux命名空间机制中管理System V IPC和POSIX消息队列的容器。当通过unshare(CLONE_NEWIPC)或setns创建新的ipc_namespace时内核调用create_ipc_ns初始化独立信号量、消息队列和共享内存的管理状态。ipcns_notify机制负责在命名空间变更时向用户态通知并提供sysctl内核参数接口。struct ipc_namespace是IPC子系统在各个命名空间中的独立副本cstruct ipc_namespace {struct ns_common ns;struct uid_gid_map uid_map;struct uid_gid_map gid_map;struct user_namespace *user_ns;struct ucounts *ucounts;int count;/* System V信号量 */struct ipc_ids sem_ids;int sc_semmni; /* 信号量集标识符上限 */int sc_semmsl; /* 每集信号量上限 */int sc_semmns; /* 系统信号量总数上限 */int sc_semopm; /* 每次semop的操作上限 */int sc_semmnu; /* undo结构上限 *//* System V消息队列 */struct ipc_ids msg_ids;int msg_ctlmax; /* 单个消息上限 */int msg_ctlmnb; /* 队列字节上限 */int msg_ctlmni; /* 队列数上限 *//* System V共享内存 */struct ipc_ids shm_ids;unsigned long shm_ctlmax;unsigned long shm_ctlall;int shm_ctlmni;int shm_rmid_forced;/* POSIX消息队列 */int mq_queues_max; /* 最大队列数 */int mq_queues_count; /* 当前队列数 */...};static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns,struct ipc_namespace *old_ns){struct ipc_namespace *ns;int err;ns kzalloc(sizeof(struct ipc_namespace), GFP_KERNEL);if (!ns)return ERR_PTR(-ENOMEM);err sem_init_ns(ns);if (err)goto fail;err msg_init_ns(ns);if (err)goto fail_sem;err shm_init_ns(ns);if (err)goto fail_msg;kref_init(ns-count);ns-user_ns get_user_ns(user_ns);ns-ucounts inc_ipc_namespaces(user_ns);...return ns;}每个IPC子系统的初始化函数sem_init_ns、msg_init_ns、shm_init_ns分别调用ipc_init_ids初始化各自的struct ipc_ids基树。每个ipc_ids包含一个struct idr基数树用于分配和查找IPC对象IDcstruct ipc_ids {int in_use; /* 当前使用中的对象数量 */unsigned short seq; /* ID序列号 */unsigned short seq_max; /* 序列号上限 */struct rhashtable key_ht; /* key哈希表 */struct idr ipcs_idr; /* ID分配基数树 */};static int __init ipc_init_ids(struct ipc_ids *ids, int min_id, int max_id){ids-in_use 0;ids-seq 0;ids-seq_max SEQ_MULTIPLIER * IPCMNI;idr_init(ids-ipcs_idr);rhltable_init(ids-key_ht, ipc_key_rht_params);return 0;}sysctl接口在kernel/sysctl.c或ipc/sysctl.c中注册。这些sysctl项使管理员可以在运行期调整每个命名空间的IPC限制cstatic struct ctl_table ipc_sysctls[] {{.procname msgmax,.data init_ipc_ns.msg_ctlmax,.maxlen sizeof(int),.mode 0644,.proc_handler proc_ipc_dointvec_minmax,.extra1 SYSCTL_ZERO,.extra2 SYSCTL_INT_MAX,},{.procname msgmnb,.data init_ipc_ns.msg_ctlmnb,.maxlen sizeof(int),.mode 0644,.proc_handler proc_ipc_dointvec_minmax,},{.procname msgmni,.data init_ipc_ns.msg_ctlmni,.maxlen sizeof(int),.mode 0644,.proc_handler proc_ipc_dointvec_minmax,},{.procname sem,.data init_ipc_ns.sem_ctls,.maxlen 4 * sizeof(int),.mode 0644,.proc_handler proc_ipc_sem_dointvec,},{.procname shmall,.data init_ipc_ns.shm_ctlall,.maxlen sizeof(unsigned long),.mode 0644,.proc_handler proc_ipc_doulongvec_minmax,},{.procname shmmax,.data init_ipc_ns.shm_ctlmax,.maxlen sizeof(unsigned long),.mode 0644,.proc_handler proc_ipc_doulongvec_minmax,},{.procname shmmni,.data init_ipc_ns.shm_ctlmni,.maxlen sizeof(int),.mode 0644,.proc_handler proc_ipc_dointvec_minmax,},{ }};proc_ipc_dointvec_minmax处理器在写入时验证值在[extra1, extra2]范围内。proc_ipc_sem_dointvec专门处理4个整数的semaphore sysctl数据。命名空间notify机制通过register_pernet_subsys向pernet_list注册回调在namespace创建或销毁时自动调用。IPC相关的pernet_operations包括cstatic struct pernet_operations sysvipc_sysctl_ops {.init sysvipc_sysctl_init,.exit sysvipc_sysctl_exit,};当新ipc_namespace创建完成后sysvipc_sysctl_init在其中注册独立的sysctl条目。进程通过/proc/sys/kernel/下的IPC参数修改的是当前命名空间的init_ipc_ns但非init命名空间的IPC sysctl自身通过/proc/self/ns/ipc隔离。每个命名空间的shm_rmid_forced等参数独立可配置互不影响。