Linux共享内存原理及系统调用分析

发布于:2025-06-07 ⋅ 阅读:(17) ⋅ 点赞:(0)

shmget 是 System V 共享内存的核心系统调用之一,其权限位(shmflg 参数)决定了共享内存段的访问控制和创建行为。以下是权限位的详细解析:


权限位的组成

shmflg 参数由两部分组成:

  1. 权限标志(低 9 位):控制用户/组/其他进程的访问权限,格式与文件权限一致(八进制表示)。
  2. 创建标志(高 位):控制共享内存段的创建行为(如 IPC_CREAT)。

1. 权限标志(八进制格式)

权限位使用 9 位二进制 表示三类用户的权限:

  • 用户(Owner)权限:前 3 位(八进制的百位)。
  • 组(Group)权限:中间 3 位(八进制的十位)。
  • 其他(Others)权限:后 3 位(八进制的个位)。
权限位的含义
二进制位 八进制值 含义
0400 4 用户可读
0200 2 用户可写
0100 1 用户可执行(通常忽略)
0040 40 组可读
0020 20 组可写
0010 10 组可执行(通常忽略)
0004 4 其他用户可读
0002 2 其他用户可写
0001 1 其他用户可执行(通常忽略)
常用权限示例
  • 0600:用户可读写,组和其他用户无权限。
  • 0644:用户可读写,组和其他用户只读。
  • 0666:所有用户可读写(需谨慎使用)。

2. 创建标志

通过按位或(|)组合以下标志,控制共享内存的创建行为:

标志 值(十六进制) 作用
IPC_CREAT 0x200 如果共享内存不存在,则创建;否则直接返回现有段的标识符。
IPC_EXCL 0x400 IPC_CREAT 联用,若共享内存已存在,则返回错误(errno = EEXIST)。
IPC_NOWAIT 0x800 非阻塞模式,若操作需等待(如资源不足),立即返回错误(较少使用)。

3. 权限检查规则

  • 创建共享内存段时
    shmflg 的权限位会写入共享内存段的 shm_perm.mode 字段,后续进程访问时需匹配这些权限。
  • 访问现有段时
    内核会检查进程的 有效用户 ID有效组 ID 是否符合权限:
    1. 若进程的 EUID 与段的所有者 EUID 相同,检查 用户权限位
    2. 若进程的 EGID 与段的组 EGID 相同,检查 组权限位
    3. 否则检查 其他用户权限位

4. 示例代码

#include <sys/ipc.h>
#include <sys/shm.h>

int main() {
    key_t key = ftok("/tmp/shm_example", 'A');  // 生成唯一键值

    // 创建共享内存段:用户可读写,组和其他用户只读
    int shmid = shmget(key, 4096, IPC_CREAT | 0644);
    if (shmid == -1) {
        perror("shmget failed");
        return 1;
    }

    // 其他操作(shmat、读写数据等)...
    return 0;
}

5. 常见问题与错误

权限不足(EACCES
  • 原因:进程没有权限访问现有共享内存段。
  • 解决方案
    1. 检查权限位是否允许当前用户/组访问。
    2. 以 root 权限运行进程(不推荐,存在安全风险)。
    3. 修改现有段的权限(需拥有者或 root 权限):
      struct shmid_ds shm_info;
      shmctl(shmid, IPC_STAT, &shm_info);
      shm_info.shm_perm.mode = 0666;  // 开放所有用户读写
      shmctl(shmid, IPC_SET, &shm_info);
      
段已存在(EEXIST
  • 原因:使用了 IPC_CREAT | IPC_EXCL,但共享内存已存在。
  • 解决方案:删除旧段或调整键值(key)。

6. 总结

  • 权限位:定义共享内存段的访问规则,格式与文件权限一致(如 0644)。
  • 创建标志IPC_CREAT 创建新段,IPC_EXCL 确保唯一性。
  • 权限检查:基于进程的 EUID/EGID 和权限位匹配。

合理设置权限位是保证共享内存安全性和功能性的关键!


网站公告

今日签到

点亮在社区的每一天
去签到