当前位置: 首页 > news >正文

Linux ipcns_notify ipc命名空间变更与sysctl接口

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子系统在各个命名空间中的独立副本:

```c
struct 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对象ID:

```c
struct 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限制:

```c
static 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包括:

```c
static 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等参数独立可配置,互不影响。

http://www.cnnetsun.cn/news/2901069.html

相关文章:

  • 如何5分钟搞定B站视频转文字:免费高效解决方案全攻略
  • 不只是科研:手把手教你用Python把‘图片放大镜’玩出花,从产品截图到教程标注都能用
  • H3C交换机端口流量监控实战:用display counters rate命令排查网络卡顿
  • 2026河北油管厂家排行揭秘,这样选才不踩坑
  • 计算机毕业设计之基于Python的校园书院预约系统的设计与实现
  • 人类最后考试已不够用,Agent最后考试来了!
  • WebSocket 行情脚本最怕的不是断线,是“看起来还在跑”
  • 如何快速获取百度网盘资源:终极提取码查询工具完整指南
  • 从“滋滋”声到清晰通话:一个移动端音频工程师的AEC避坑实战录
  • 别再只用矢量数据了!一文讲透ArcGIS中哪些栅格数据有属性表,以及如何利用
  • 豹女红三速开 目前1min57s
  • 深度解析CANN昇腾AI处理器算子开发中的调试工具链与性能调优实战指南
  • 三步解锁《鸣潮》极致体验:WaveTools工具箱实战指南
  • 2026 APMCM 亚太地区大学生数学建模竞赛 ABC
  • 51单片机矩阵键盘密码锁实战:从硬件连线到代码调试,手把手教你避开蜂鸣器干扰
  • 一文看懂 AI 编程智能体工程化新范式:Loop Engineering
  • Python周刊2026W23 | Polars 1.41、PyPy v7.3.23、Python 3.15、httpx2、dj-lite-tenant
  • 手把手教你用MTK DWS配置GPIO驱动LED和按键(基于MT6765平台)
  • 用Scrapy搭建基础网络文本爬虫的完整实践指南
  • 手把手教你优化STM32H7性能:把关键代码和数据塞进ITCM/DTCM的完整流程
  • GOT-JEPA:通用目标跟踪的创新架构与遮挡处理技术
  • 告别单体应用:用SpringCloudAlibaba快速拆分出你的第一个微服务(Order/Stock实战)
  • Centos7.9搭建IPV6银河麒麟SP2系统PXE
  • 别再死记公式了!用STM32CubeMX配置ADC测芯片内部温度,附F0/F1系列校准值查找与代码实战
  • 保姆级教程:在Win10上用Docker Desktop搞定ChirpStack服务器,手把手连接Ra-08H收发MQTT数据
  • 从零到封装:用Logisim搭建你的第一个可复用LED计数器模块
  • 如何3步免费解锁123云盘VIP功能?完整实用教程
  • WinForm程序运行中实时编译C#代码并调用方法的完整示例
  • ESP32开发效率翻倍:详解VSCode中ESP-IDF插件的7个隐藏技巧与idf.py命令组合
  • 告别插件!用QGIS 3.16自带栅格工具,5分钟搞定星图地球XYZ瓦片下载与Leaflet离线部署