共享内存

  • sys/shm.h
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
int main(void){
    // 创建一个ipc的key
    key_t k = ftok(".",8);
    // 通过key创建或获取共享内存ID 返回共享内存ID 失败返回-1
    /*
     * shmget 创建或获取共享内存ID
     *  key: ftok函数返回的key
     *  size 要开辟内存空间的字节数,按页取整
     *  shmflg 标志位置
     *      0           - 获取 不存在即失败(是否存在根据key来判断)
     *      IPC_CERAT   - 创建 不存在即创建,已存在即获取(是否存在根据key来判断)
     *      IPC_EXCL    - 排它 不存在即创建,已存在即失败(是否存在根据key来判断)
     * */
    // 表示创建权限为0664内存不获取旧的内存
    int mid = shmget(k, sizeof(int ),IPC_CREAT | IPC_EXCL | 0664);
    if (mid == -1){
        perror("shmget");
        return -1;
    }
    // 加载共享内存 返回共享内存的起始地址 失败返回 (void*)-1
    /*
     * shmat            加载共享内存
     *  shmid           共享内存的ID
     *  shmaddr         共享内存的下虚拟内存起始地址,NULL则由系统自动选择
     *  shmflg          加载标志
     *      0           以读写的方式共享
     *      SHM_RDONLY 以只读的方式共享
     * */
    shmat();
    // 解除内存映射关系
    /*
     * shmdt 解除内存映射关系
     *  shmaddr 需要解除映射的内存首地址
     *
     * 成功 返回0 失败返回-1
     * */
    shmdt();
    // 控制共享内存
    /*
     * shmctl  控制共享内存
     *  shmid 要操作的共享内存ID
     *  cmd   要做的操作
     *      IPC_RMID 销毁共享内存
     *  buf NULL
     *  成功返回0 失败返回-1
     *  备注:调用销毁时,并非立即销毁,需要加载计数为0时才真正销毁;并且其他进程无法创建与这块共享内存的映射,之前已经创建的不受影响
     * */
    shmctl();
    return 0;
}
  • 写数据
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <unistd.h>

int main(void){
    // 创建key
    key_t k = ftok(".",8);
    if (k == 0xffffffff){
        perror("ftok");
        return -1;
    }
    // 通过key创建共享空间,获取共享空间的ID
    printf("%d:创建共享空间\n",getpid());
    int mid = shmget(k, 4096,IPC_CREAT | IPC_EXCL | 0664);
    if (mid == -1){
        perror("shmget");
        return -1;
    }
    // 将共享空间的ID映射到虚拟内存表(加载空间)
    printf("%d:加载空间\n",getpid());
    void* shmatAddr = shmat(mid,NULL,0);
    if (shmatAddr == (void*)-1){
        perror("shmat");
        return -1;
    }

    // 在共享内存中写入数据
    printf("%d:写入数据\n",getpid());
    if(sprintf(shmatAddr,"KEY=%x;PID=%d;shmatAddr=%p",k,getpid(),shmatAddr) == -1){
        perror("sprintf");
        return -1;
    }
    // 卸载共享空间
    printf("%d:卸载共享空间\n",getpid());
    if (shmdt(shmatAddr) == -1){
        perror("shmat");
        return -1;
    }
    getchar();
    // 销毁共享空间
    printf("%d:销毁共享空间\n",getpid());
    if(shmctl(mid,IPC_RMID,NULL)==-1){
        perror("销毁共享空间");
        return -1;
    }
    return 0;
}
  • 读数据
#include <stdlib.h>
#include <stdio.h>
#include <sys/shm.h>
#include <unistd.h>
int main(void){
    // 创建key
    key_t k = ftok(".",8);
    if (k == 0xffffffff){
        perror("ftok");
        return -1;
    }
    // 通过key获取空间,获取共享空间的ID
    printf("%d:获取共享空间\n",getpid());
    int mid = shmget(k, 0,0);
    if (mid == -1){
        perror("shmget");
        return -1;
    }
    // 将共享空间的ID映射到虚拟内存表(加载空间)
    printf("%d:加载空间\n",getpid());
    void* shmatAddr = shmat(mid,NULL,0);
    if (shmatAddr == (void*)-1){
        perror("shmat");
        return -1;
    }

    // 读取共享空间中的数据v
    printf("%d:读取数据\n",getpid());
    printf("%s\n",(char*)shmatAddr);
    // 卸载共享空间
    printf("%d:卸载共享空间\n",getpid());
    if (shmdt(shmatAddr) == -1){
        perror("shmat");
        return -1;
    }
    return 0;

}

posted on 2023-05-03 15:31  信奉上帝的小和尚  阅读(6)  评论(0编辑  收藏  举报

导航