共享内存 shmget函数

本文深入讲解了共享内存机制中的核心函数shmget、shmat、shmdt和shmctl的使用方法,并通过一个通信实例展示了如何利用这些函数实现进程间的共享内存通信。

内核共享内存


shmget

头文件 函数

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

// 得到一个共享内存标识符或创建一个共享内存对象并返回共享内存标识符
int shmget(key_t key, size_t size, int shmflg)
// 成功:返回共享内存的标识符; 出错:-1,错误原因存于error中
key会建立新共享内存对象
size大于0的整数:新建的共享内存大小,以字节为单位
size = 0只获取共享内存时指定为0
shmflg共享内存标识符
shmflg = IPC_CREAT如果内核中不存在键值与key相等的共享内存,则新建一个共享内存;如果存在这样的共享内存,返回此共享内存的标识符
shmflg = IPC_CREAT | IPC_EXCL如果内核中不存在键值 与key相等的共享内存,则新建一个共享内存;如果存在这样的共享内存则报错
shmflg = 0取共享内存标识符,若不存在则函数会报错

shmat

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

// 连接共享内存标识符为shmid的共享内存,连接成功后把共享内存区对象映射到调用进程的地址空间,随后可像本地空间一样访问
void *shmat(int shmid, const void *shmaddr, int shmflg)
// 成功:附加好的共享内存地址;出错:-1,错误原因存于error中
shmid共享内存标识符
shmaddr指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核自己决定一个合适的地址位置
shmflgSHM_RDONLY:为只读模式,0 为读写模式

shmdt

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

// 连接的共享内存
int shmdt(const void *shmaddr)
// 成功:0; 出错:-1,错误原因存于error中
shmaddr连接的共享内存的起始地址

shmctl

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

// 完成对共享内存的控制
int shmctl(int shmid, int cmd, struct shmid_ds *buf)
// 成功:0; 出错:-1,错误原因存于error中

shmid共享内存标识符
cmd =IPC_STAT得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中
cmd = IPC_SET改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode复制到共享内存的shmid_ds结构内
cmd = IPC_RMID删除这片共享内存
buf共享内存管理结构体。具体说明参见共享内存内核结构定义部分

一个通信例子

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <string.h>

#define addr 0x8888

int get_id(int num)
{
    int id;
    if (num > 0)
    {
        // 第一次申请了64哥字节的空间
        id = shmget(addr, 64, IPC_CREAT | IPC_EXCL | 0664);
        // 把共享内存区映射到进程的地址空间
        char *s = (char *)shmat(id, NULL, 0);
        s = NULL;
        // 链接共享单元
        shmdt(s);
    }
    else
        // 共享单元已经创建的时侯, 进行连接就行, 不用创建了
        id = shmget(addr, 0, 0);

    return id;
}

int main(int argc, char *argv[])
{
    // argv[1] > 0 第一次, 建立共享空间, 并连接
    // argv[0] = 0 直接进行连接
    int id = get_id(atoi(argv[1]));
    char *s = (char *)shmat(id, 0, 0);
    char buf[1024];

    if (argv[2][0] == 'w')
    {
        int i;
        read(1, buf, sizeof(buf));
        i = 0;
        while (buf[i] != '\0')
            s[i] = buf[i++];
        s[i] = '\0';
    }
    else if (argv[2][0] == 'r')
        write(0, s, strlen(s));
    else if (argv[2][0] == 'd')
        shmctl(id, IPC_RMID, 0);

    exit(EXIT_SUCCESS);
}

运行截图

这里写图片描述
记住, 最后一定要用 否则创建的共享区会一直在关机前都会存在, 不会释放通过 . ipcs查看共享空间块

./aout 0 d
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值