博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
共享内存
阅读量:2432 次
发布时间:2019-05-10

本文共 3512 字,大约阅读时间需要 11 分钟。

使用共享内存的步骤
#include <sys/ipc.h>
#include <sys/shm.h>
1 创建
int shmget(key_t key, size_t size, int shmflg);
2 attach
void *shmat(int shmid, const void *shmaddr, int shmflg);
3 使用
和使用malloc的内存一样。
4 detach
int shmdt(const void *shmaddr);
5 删除
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
创建共享内存段和创建信号量非常相似,都是值得一个key,然后返回一个id。
int key = 9999;
int id = shmget((key_t)key, size, 0666|IPC_CREAT|IPC_EXCL)
如果返回的id是-1,说明创建失败。此时需要判断errno,如果errno等于EEXIST,说明共享内存段已经存在。
if(errno == EEXIST)
{
    if((id = shmget((key_t)key, size, 0)) < 0)
    {
        return -1;
    }
    else
    {
        printf("get exists shared memory: %d\n", id);
    }
}
其它可能的错误:
     EACCES 权限问题
     EEXIST 相同key的共享内存段已经存在
     EINVAL 多种原因,比如指定的size不符合SHMMIN和SHMMAX
     ENFILE 超出文件描述符限制
     ENOENT 没有找到指定key对应的共享内存段,同时又没有指定IPC_CREAT
     ENOMEM 内存不足
     ENOSPC 共享内存的ID用完了(SHMMNI), 或者超过共享内存的系统限制(SHMALL)
     EPERM  指定了SHM_HUGETLB,但是没有权限(did not have the CAP_IPC_LOCK capability)
得到共享内存端的id之后,就可以attach。attach就是把共享内存的地址映射到自己的地址空间里。
void* p = shmat(id, NULL, 0666);
第一个参数是shmget得到的id
第二个参数是希望映射到的地址,如果不指定,就会自动映射一个地址。
第三个参数和其它函数一样。
返回的指针是实际映射到的地址。
attach得到的地址传给shmdt就可以完成detach
int shmdt(const void *shmaddr);
删除共享内存段
shmctl(id,IPC_RMID, NULL);
完整例子
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
int initshm(int key, int size, void** p)
{
    int id = 0;
    if((id = shmget((key_t)key, size, 0666|IPC_CREAT|IPC_EXCL)) < 0)
    {
        if(errno == EEXIST)
        {
            if((id = shmget((key_t)key, size, 0)) < 0)
            {
                return -1;
            }
            else
            {
                printf("get exists shared memory: %d\n", id);
            }
        }
    }
    else
    {
        printf("create shared memory: %d\n", id);
    }
    if((*p = shmat(id, NULL, 0666)) == NULL)
    {
        return -1;
    }
    return id;
}
int delshm(int id)
{
    return shmctl(id,IPC_RMID, NULL);
}
int main()
{
    int key = ftok("a.c", 1);
    int id = 0;
    char* p = NULL;
    if((id = initshm(key, BUFSIZ, (void**)&p)) < 0)
    {
        printf("shmget(): %s\b", strerror(errno));
        exit(1);
    }
    char cmd[BUFSIZ];
    char str[BUFSIZ];
    while(1)
    {
        puts("p for print.");
        puts("w for write.");
        puts("q for exit.");
        scanf("%s", cmd);
        if(strcmp(cmd, "p") == 0)
        {
            printf("share memory: %s\n", p);
        }
        else if(strcmp(cmd, "w") == 0)
        {
            scanf("%s", str);
            strcpy(p, str);
        }
        else if(strcmp(cmd, "q") == 0)
        {
            exit(0);
        }
        else
        {
            continue;
        }   
    }
    if(delshm(id) == 0)
    {
        printf("shared memory %d deleted.\n", id);
    }
    else
    {
        printf("shmget(): %s\b", strerror(errno));
        exit(1);
    }
    exit(0);
}
使用方法
shell 1
提示创建了共享内存
[root@server2 shm]# ./a
create shared memory: 393221
p for print.
w for write.
q for exit.
shell 2
提示得到已存在的共享内存
[root@server2 shm]# ./a
get exists shared memory: 393221
p for print.
w for write.
q for exit.
shell 1
按w回车,然后输出字符串后按回车
w
abcdef
shell 2
按p回车,输出shell 1保存到共享内存里的内容
share memory: abcdef
然后shell 1 和 shell 2 可以交替修改和打印共享内存段。
此时可以看到这个共享内存段有两个attach
[root@server2 ~]# ipcs -m
------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status     
0x00000000 0          gdm        600        393216     2          dest         
0x00000000 32769      gdm        600        393216     2          dest         
0x00000000 65538      gdm        600        393216     2          dest         
0x00000000 98307      gdm        600        393216     2          dest                     
0x01026a7d 393221     root       666        8192       2
两个程序都推出后,attach被系统自动清理
[root@server2 ~]# ipcs -m
------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status     
0x00000000 0          gdm        600        393216     2          dest         
0x00000000 32769      gdm        600        393216     2          dest         
0x00000000 65538      gdm        600        393216     2          dest         
0x00000000 98307      gdm        600        393216     2          dest                          
0x01026a7d 393221     root       666        8192       0 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26239116/viewspace-2075998/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/26239116/viewspace-2075998/

你可能感兴趣的文章
移动通信的主要测量指标及注意事项(转)
查看>>
无盘网络正确网络配置建议-减少卡机蓝屏关键(转)
查看>>
如何在Delphi中调用oracle的存储过程返回数据集(转)
查看>>
ASP指南:ADO/SQL(数据存取) (转)
查看>>
赛门铁克报告启发 黑客示范如何攻入Vista!(转)
查看>>
移动通信的两种新型天线(转)
查看>>
用本地 C++ 应对大量 Series 60 图形(转)
查看>>
微软将在HEC上发布Windows 2003 64-bit(转)
查看>>
ORA-01502 state unusable错误成因和解决方法(转)
查看>>
Robots.txt指南(转)
查看>>
保护SQL Server数据库的十大绝招(转)
查看>>
IVR业务制作技巧(转)
查看>>
SEO现状:网络营销之SEO骗子多(转)
查看>>
Peeking in MySQL 5.0 Enterprise Functional(转)
查看>>
系统硬件资源和 Emulator 模拟(转)
查看>>
百度搜索引擎使用指南(转)
查看>>
专家观点:安全成交换机的基本功能(转)
查看>>
树型结构在ASP中的简单解决(转)
查看>>
解决玩游戏时显卡卡屏现象(转)
查看>>
移动通信概要(转)
查看>>