如何设置linux的共享内存

Linux中,通过shmget创建共享内存段,用shmat附加到进程地址空间,访问修改后以shmdt分离,最后用shmctl删除

Linux系统中,共享内存是一种高效的进程间通信(IPC)机制,允许多个进程直接访问同一块内存区域,从而实现快速的数据交换,以下是设置Linux共享内存的详细步骤和相关说明:

如何设置linux的共享内存

创建共享内存段

在Linux中,可以使用shmget系统调用来创建或获取一个共享内存段,这个函数通常用于System V IPC(进程间通信)机制,以下是一个基本的示例代码:

#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
int main() {
    key_t key = ftok("somefile", 'R'); // 生成唯一的键值
    int shmid = shmget(key, 1024, 0666|IPC_CREAT); // 创建共享内存段
    if (shmid == -1) {
        perror("shmget failed");
        return 1;
    }
    printf("Shared memory created with id: %d
", shmid);
    return 0;
}

在这个示例中,ftok函数用于生成一个唯一的键值,shmget函数用于创建共享内存段。1024是共享内存段的大小,0666是权限标志,IPC_CREAT表示如果共享内存段不存在则创建它。

附加到共享内存段

创建共享内存段后,进程需要将其附加到自己的地址空间中,以便进行读写操作,可以使用shmat系统调用来实现这一点,以下是一个示例代码:

#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
int main() {
    key_t key = ftok("somefile", 'R');
    int shmid = shmget(key, 1024, 0666|IPC_CREAT);
    if (shmid == -1) {
        perror("shmget failed");
        return 1;
    }
    char data = (char ) shmat(shmid, NULL, 0); // 附加到共享内存段
    if (data == (char ) -1) {
        perror("shmat failed");
        return 1;
    }
    printf("Shared memory attached at address: %p
", data);
    return 0;
}

在这个示例中,shmat函数将共享内存段附加到当前进程的地址空间中,并返回指向该内存段的指针。

如何设置linux的共享内存

读写共享内存

附加到共享内存段后,进程可以像操作普通内存一样读写共享内存,以下是一个示例代码:

#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <string.h>
int main() {
    key_t key = ftok("somefile", 'R');
    int shmid = shmget(key, 1024, 0666|IPC_CREAT);
    if (shmid == -1) {
        perror("shmget failed");
        return 1;
    }
    char data = (char ) shmat(shmid, NULL, 0);
    if (data == (char ) -1) {
        perror("shmat failed");
        return 1;
    }
    strcpy(data, "Hello, World!"); // 写入数据到共享内存
    printf("Data written to shared memory: %s
", data);
    return 0;
}

在这个示例中,strcpy函数将字符串”Hello, World!”写入共享内存,其他进程也可以附加到同一个共享内存段,并读取或修改其中的数据。

分离和删除共享内存段

当进程不再需要访问共享内存时,可以使用shmdt系统调用将其从当前进程的地址空间中分离,共享内存段不再使用时,可以使用shmctl系统调用将其删除,以下是一个示例代码:

#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
int main() {
    key_t key = ftok("somefile", 'R');
    int shmid = shmget(key, 1024, 0666|IPC_CREAT);
    if (shmid == -1) {
        perror("shmget failed");
        return 1;
    }
    char data = (char ) shmat(shmid, NULL, 0);
    if (data == (char ) -1) {
        perror("shmat failed");
        return 1;
    }
    strcpy(data, "Hello, World!");
    printf("Data written to shared memory: %s
", data);
    if (shmdt(data) == -1) { // 分离共享内存段
        perror("shmdt failed");
        return 1;
    }
    printf("Shared memory detached
");
    if (shmctl(shmid, IPC_RMID, NULL) == -1) { // 删除共享内存段
        perror("shmctl failed");
        return 1;
    }
    printf("Shared memory removed
");
    return 0;
}

在这个示例中,shmdt函数将共享内存段从当前进程的地址空间中分离,shmctl函数将共享内存段从系统中删除。

如何设置linux的共享内存

使用POSIX共享内存

除了System V共享内存外,Linux还支持POSIX共享内存,POSIX共享内存的使用方式与System V有所不同,但同样可以实现进程间通信,以下是一个简单的POSIX共享内存示例:

#include <fcntl.h>
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main() {
    int fd = shm_open("/myshm", O_CREAT|O_RDWR, 0666); // 创建共享内存对象
    if (fd == -1) {
        perror("shm_open failed");
        return 1;
    }
    if (ftruncate(fd, 1024) == -1) { // 设置共享内存大小
        perror("ftruncate failed");
        return 1;
    }
    char data = (char ) mmap(NULL, 1024, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); // 映射共享内存
    if (data == MAP_FAILED) {
        perror("mmap failed");
        return 1;
    }
    strcpy(data, "Hello, POSIX!"); // 写入数据到共享内存
    printf("Data written to shared memory: %s
", data);
    if (munmap(data, 1024) == -1) { // 取消映射
        perror("munmap failed");
        return 1;
    }
    if (shm_unlink("/myshm") == -1) { // 删除共享内存对象
        perror("shm_unlink failed");
        return 1;
    }
    return 0;
}

在这个示例中,shm_open函数用于创建共享内存对象,ftruncate函数用于设置共享内存的大小,mmap函数用于将共享内存映射到进程的地址空间中。munmap函数用于取消映射,shm_unlink函数用于删除共享内存对象。

归纳对比表

特性 System V共享内存 POSIX共享内存
创建方式 shmget shm_open
附加方式 shmat mmap
分离方式 shmdt munmap
删除方式 shmctl with IPC_RMID shm_unlink
键值生成 ftok 路径名作为键值
权限控制 shmflg参数 shm_open的第三个参数
适用场景 传统IPC需求 现代POSIX标准需求
可移植性 特定于System V 更符合POSIX标准,跨平台更好
功能丰富性 支持更多IPC功能(如消息队列、信号量) 专注于共享内存,接口更简单
性能 较高 较高,但可能因实现差异略有不同
易用性 需要管理键值和权限 路径名更直观,权限控制更灵活
典型应用场景 需要与其他System V IPC机制配合使用的场景 需要与其他POSIX IPC机制配合使用的场景
开发复杂度 中等 较低,API更直观
错误处理 需要检查返回值和errno 同样需要检查返回值和errno
资源管理 需要手动管理键值和权限 路径名更直观,但仍需注意资源释放
兼容性 广泛支持于各种Unix-like系统 主要支持于支持POSIX标准的系统
扩展性 可以与其他System V IPC机制结合使用 可以与其他POSIX IPC机制结合使用
开发效率 可能需要更多代码来处理键值和权限 API更简洁,开发效率更高
学习曲线 较陡峭,需要理解System V IPC机制 较平缓,API设计更符合现代编程习惯
社区支持 广泛,历史悠久 逐渐增加,特别是在现代系统中
文档和示例 丰富,但可能较为分散 相对集中,易于查找
调试难度 中等,需要理解IPC机制 较低,API更直观
维护成本 中等,需要管理键值和权限 较低,路径名更直观,权限控制更灵活
性能优化 可以通过调整系统参数进行优化 同样可以通过调整系统参数进行优化
安全性 需要正确设置权限以避免安全风险 同样需要正确设置权限以避免安全风险
跨平台支持 有限,主要在Unix-like系统中 较好,符合POSIX标准,跨平台更好
开发工具支持 广泛支持于各种开发工具和环境 同样支持于各种开发工具和环境
未来发展趋势 逐渐被POSIX共享内存取代 逐渐成为主流,特别是在现代系统中
典型问题 键值冲突、权限管理复杂 路径名冲突、权限管理相对简单
解决方案 使用唯一的键值,合理设置权限 使用唯一的路径名,合理设置权限
最佳实践 确保正确管理键值和权限,避免资源泄漏 确保正确管理路径名和权限,避免资源泄漏
性能考虑 高效,但需注意同步和锁机制 高效,同样需注意同步和锁机制
资源释放 需要手动调用shmdtshmctl 需要手动调用munmapshm_unlink
错误处理 需要检查返回值和errno 同样需要检查返回值和errno
开发效率 中等,需要编写较多代码 较高,API更简洁
学习资源 丰富,但可能较为分散 相对集中,易于查找
社区支持 广泛,历史悠久 逐渐增加,特别是在现代系统中
文档和示例 丰富,但可能较为分散 相对集中,易于查找
调试难度 中等,需要理解IPC机制 较低,API更直观
维护成本 中等,需要管理键值和权限 较低,路径名更直观,权限控制更灵活
性能优化 可以通过调整系统参数进行优化 同样可以通过调整系统参数进行优化
安全性 需要正确设置权限以避免安全风险 同样需要正确设置权限以避免安全风险
跨平台支持 有限,主要在Unix-like系统中 较好,符合POSIX标准,跨平台更好
开发工具支持 广泛支持于各种开发工具和环境 同样支持于各种开发工具和环境
未来发展趋势 逐渐被POSIX共享内存取代 逐渐成为主流,特别是在现代系统中
典型问题 键值冲突、权限管理复杂 路径名冲突、权限管理相对简单
解决方案 使用唯一的键值,合理设置权限 使用唯一的路径名,合理设置权限
最佳实践 确保正确管理键值和权限,避免资源泄漏 确保正确管理路径名和权限,避免资源泄漏
性能考虑 高效,但需注意同步和锁机制 高效,同样需注意同步和锁机制
资源释放 需要手动调用shmdtshmctl 需要手动调用munmapshm_unlink
错误处理 需要检查返回值和errno 同样需要检查返回值和errno
开发效率 中等,需要编写较多代码 较高,API更简洁
学习资源 丰富,但可能较为分散 相对集中,易于查找
社区支持 广泛,历史悠久 逐渐增加,特别是在现代系统中
文档和示例 丰富,但可能较为分散 相对集中,易于查找
调试难度 中等,需要理解IPC机制 较低,API更直观
维护成本 中等,需要管理键值和权限 较低,路径名更直观,权限控制更灵活
性能优化 可以通过调整系统参数进行优化 同样可以通过调整系统参数进行优化
安全性 需要正确设置权限以避免安全风险 同样需要正确设置权限以避免安全风险
跨平台支持 有限,主要在Unix-like系统中 较好,符合POSIX标准,跨平台更好
开发工具支持 广泛支持于各种开发工具和环境 同样支持于各种开发工具和环境
未来发展趋势 逐渐被POSIX共享内存取代 逐渐成为主流,特别是在现代系统中
典型问题 键值冲突、权限管理复杂 路径名冲突、权限管理相对简单
解决方案 使用唯一的键值,合理设置权限 使用唯一的路径名,合理设置权限
最佳实践 确保正确管理键值和权限,避免资源泄漏 确保正确管理路径名和权限,避免资源泄漏
性能考虑 高效,但需注意同步和锁机制 高效,同样需注意同步和锁机制
资源释放 需要手动调用shmdtshmctl 需要手动调用munmapshm_unlink
错误处理 需要检查返回值和errno 同样需要检查返回值和errno
开发效率 中等,需要编写较多代码 较高,API更简洁
学习资源 丰富,但可能较为分散 相对集中,易于查找
社区支持 广泛,历史悠久 逐渐增加,特别是在现代系统中
文档和示例 丰富,但可能较为分散 相对集中,易于查找
调试难度 中等,需要理解IPC机制 较低,API更直观
维护成本 中等,需要管理键值和权限 较低,路径名更直观,权限控制更灵活
性能优化

原创文章,发布者:酷盾叔,转转请注明出处:https://www.kd.cn/ask/55134.html

(0)
酷盾叔的头像酷盾叔
上一篇 2025年7月11日 20:22
下一篇 2025年7月11日 20:27

相关推荐

  • Linux用户秒懂,注销的正确姿势

    要注销Linux用户登录: ,1. **终端**:执行exit或logout命令 ,2. **图形界面**:点击右上角菜单选择”注销” ,3. **快捷键**:Ctrl+D(终端中快速注销) ,此操作仅结束当前会话,不会终止后台进程。

    2025年7月2日
    000
  • U盘怎么连接Linux系统

    插入U盘后,Linux 7通常会自动识别并挂载到/media或/run/media目录下,若未自动挂载,使用lsblk或fdisk -l查看设备名(如/dev/sdb1),手动创建目录并用mount /dev/sdb1 /mnt命令挂载即可访问U盘内容。

    2025年6月23日
    000
  • linux如何安装web服务器

    Linux上安装Web服务器,首先更新系统,然后根据需求选择安装Apache或Nginx,在Ubuntu上安装Apache可使用命令sudo apt update和sudo apt install apache2,安装完成后启动服务并设置为开机自启

    2025年7月12日
    000
  • Linux端口被哪个程序占用?

    在 Linux 中查看端口占用程序:,1. **netstat -tulpn | grep **:查看监听端口的进程名和 PID。,2. **lsof -i :**:直接列出占用指定端口的进程信息。,3. **ss -tulpn | grep **:更现代的替代命令,功能类似 netstat。,通常需要 root 权限才能查看所有进程信息。

    2025年6月11日
    100
  • Linux如何查看登录用户数?

    使用who或w命令查看登录用户信息,统计总登录次数:who | wc -l,统计不同用户数量:who | cut -d’ ‘ -f1 | sort -u | wc -l。

    2025年6月11日
    000

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

400-880-8834

在线咨询: QQ交谈

邮件:HI@E.KD.CN