ftok

通过文件路径 pathname 以及 proj_id 获得键值key(键值:共享内存的标识),只要文件路径和proj_id不变,key值就不变

头文件:
    #include <sys/types.h>
    #include <sys/ipc.h>
原型:
    key_t ftok(const char *pathname, int proj_id);
参数:
    char *pathname:文件路径(目录文件或是普通文件);
    int proj_id:非0参数,用户自定义;
返回值:
    成功,返回key值;
    失败,返回-1,更新errno;
例程:
    key_t key = ftok("./", 'a');
    if(key < 0)
    {
        perror("ftok");
        return -1;
    }
    printf("key = %x\n", key);

shmget

创建或打开共享内存对象

头文件:
    #include <sys/ipc.h>
    #include <sys/shm.h>
原型:
    int shmget(key_t key, size_t size, int shmflg);
参数:
    key_t key:键值,提前约定或ftok函数创建获得;
    size_t size:指定创建的共享内存空间大小,以字节为单位;
    int shmflg:设置共享内存的访问权限,参数如下:
        IPC_CREAT:若共享内存对象不存在则创建,否则打开已经存在的共享内存对象;
        IPC_EXCL:若共享内存对象不存在则创建,否则返回出错;
        IPC_NOWAIT:(非阻塞)如果本操作需要等待,则直接返回错误;
            IPC_CREAT|0666:如果内核中不存在与key值相同的共享内存,则创建共享内存,并设置8进制权限(按位或)。如果存在,则直接返回共享内存标识符shmid;
返回值:
    成功,返回共享内存标识符:shmid;
    失败,返回-1,更新errno;
例程:
    int shmid = shmget(key, N, IPC_CREAT|0664);
    if(shmid < 0)
    {
        perror("shmget");
        return -1;
    }
    printf("shmid = %d\n", shmid);

shmat

将共享内存空间连接到进程的虚拟地址空间

头文件:
    #include <sys/types.h>
    #include <sys/shm.h>
原型:
    void *shmat(int shmid, const void *shmaddr, int shmflg);
参数:
    int shmid:共享内存对象标识id;
    void *shmaddr:共享内存映射到进程空间的虚拟地址,填NULL,让系统决定共享内存连接到进程空间中的哪个地址;
    int shmflg:参数如下:
        0:可读可写;
        SHM_RDONLY:共享内存被限制为只读;
返回值:
    成功,返回共享内存映射到用户空间的地址;
    失败,返回(void *) -1,更新errno;
例程:
    void* shmaddr = NULL;
    shmaddr = shmat(shmid, NULL, 0);
    if(shmaddr == (void*)-1)
    {
        perror("shmat");
        return -1;
    }
    printf("shmaddr = %p\n", shmaddr);

shmdt

断开进程空间与共享内存空间的连接

头文件:
    #include <sys/types.h>
    #include <sys/shm.h>
原型:
    int shmdt(const void *shmaddr);
参数:
    void *shmaddr:指定要断开映射的内存空间在进程空间中的连接地址;
返回值:
    成功,返回0;
    失败,返回-1,更新errno;
例程:
    if(shmdt(shmaddr) < 0)
    {
        perror("shmdt");
        return -1;
    }

shmctl

共享内存控制操作,常用于删除

头文件:
    #include <sys/ipc.h>
    #include <sys/shm.h>
原型:
    int shmctl(int shmid, int cmd, struct shmid_ds *buf);
参数:
    int shmid:共享内存的shmid
    int cmd:控制方式,参数如下:
        IPC_RMID:删除共享内存,第三个参数,填NULL;
        IPC_STAT:获取共享内存对象的内核结构值,存放到第三个参数中;
        IPC_SET:设置共享内存对象的内核结构值;
    struct shmid_ds *buf:指向shmid_ds结构的指针;
返回值:
    成功,返回0;
    失败,返回-1,更新errno;
例程:
    if(shmctl(shmid, IPC_RMID, NULL) < 0)
    {
        perror("shmctl");
        return -1;
    }

往共享内存中 写数据

strcpy((char*)shmaddr,"hello world");

向共享内存中 读数据

char str[20] = "";
strcpy(str,(char*)shmaddr);

应用例程

使用共享内存实现,一个进程写入数据,一个进程读取数据

进程1:写入数据到共享内存

#include <stdio.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <string.h>
#define N 20
int main(int argc, const char *argv[])
{
    //创建共享内存key值
    key_t key = ftok("./",'a');
    if(key < 0){
        perror("ftok");
        return -1;
    }
    printf("key = %x\n",key);
    //创建共享内存
    int shmid = shmget(key,N,IPC_CREAT|0664);
    if(shmid < 0){
        perror("shmget");
        return -1;
    }
    printf("shmid = %d\n",shmid);
    //映射到虚拟内存地址
    void* shmaddr = shmat(shmid,NULL,0);
    if(shmaddr == (void*)-1){
        perror("shmat");
        return -1;
    }
    //将数据存入共享内存
    strcpy((char*)shmaddr,"Shared Memory");
    //断开映射
    if(shmdt(shmaddr) < 0){
        perror("shmdt");
        return -1;
    }
    return 0;
}

进程2:从共享内存中读取数据

#include <stdio.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <string.h>
#define N 20
int main(int argc, const char *argv[])
{
    //获取共享内存key值
    key_t key = ftok("./",'a');   
    if(key < 0){   
        perror("ftok");
        return -1; 
    }
    printf("key = %x\n",key);
    //创建共享内存
    int shmid = shmget(key,N,IPC_CREAT|0664);  
    if(shmid < 0){   
        perror("shmget");
        return -1;
    }
    printf("shmid = %d\n",shmid);
    //映射到虚拟内存地址
    void* shmaddr = shmat(shmid,NULL,0);  
    if(shmaddr == (void*)-1){   
        perror("shmat");
        return -1; 
    }   
    //从虚拟内存中获取数据拷贝
    char str[N] = "";
    strcpy(str,(char*)shmaddr);
    puts(str);
    //断开映射
    if(shmdt(shmaddr) < 0){
        perror("shmdt");
        return -1;
    }
    //删除共享内存
    if(shmctl(shmid,IPC_RMID,NULL) < 0){
        perror("shmctl");
        return -1;
    }
    return 0;
}

结果

Last modification:2021 年 04 月 07 日 19 : 25 : 34