Linux IPC进程间通信(二):共享内存

系列文章:
Linux IPC进程间通信(一):管道
Linux IPC进程间通信(二):共享内存
Linux IPC进程间通信(三):信号量
Linux IPC进程间通信(四):消息队列


文章目录

      • 共享内存
      • 案例一:亲属进程间通信
      • 案例二:非亲属进程通信

共享内存

  • key_t ftok(const char* filename, int proj_id)

通过已经存在的文件(filename) 与 proj_id(通常大于0) 创建出一个key值,用于进行共享内存的生成。

  • int shmget(key_t key, size_t size, int shmflag)

key代表着与共享内存相关的一个关键字,如果该关键字已经存在,那么直接打开该共享内存,反之创建共享内存(一般使用 IPC_PRIVATE 用于创建新的共享内存)
size代表共享内存的大小
shmflag表示权限(一般为0600), 如果时要进行创建的话则是 IPC_CREAT, 也可以加上 IPC_EXCL , 代表必须创建新的共享内存,已有则返回-1
成功返回shmid(共享内存段的id),失败返回-1

  • void* shmat(int shmid, char* shmaddr, int shmflag)

操作类似mmap内存映射。
shmid代表已经存在的共享内存id
shmaddr代表是否需要自定义共享内存映射到特定位置(一般为NULL,让系统来选择)
shmflag代表位标识(通常为0)
成功返回共享内存段的首地址,失败返回(void*)-1

  • int shmctl(int shmid, int cmd, shmid_ds* buf)

一般用来删除共享内存段
shmid 代表共享内存段号
cmd 代表执行命令(一般为 IPC_RMID)
buf 结构体的信息(一般为NULL)

如果想要使用结构体的信息,也可以在cmd命令中输入 IPC_STAT 来获取结构体的信息,或是 IPC_SET 来设置结构体信息以改变共享内存

int test0()
{
    int ret;
    key_t key = ftok("file", 1);
    ERROR_CHECK(key, -1, "ftok")
    int shmid = shmget(key, 1024, 0600 | IPC_CREAT);
    ERROR_CHECK(shmid, -1, "shmget");
    char *buf = (char *)shmat(shmid, NULL, 0);
    ERROR_CHECK(buf, (char *)-1, "shmat");
    strcpy(buf, "hello");
    cout << "shared memory:" << buf << endl;
    struct shmid_ds shminfo;
    ret = shmctl(shmid, IPC_STAT, &shminfo);
    ERROR_CHECK(ret, -1 , "IPC_STAT");
    cout << shminfo.shm_perm.cgid << endl;
    shminfo.shm_perm.cgid = 666;
    shmctl(shmid, IPC_SET, &shminfo);
    cout << shminfo.shm_perm.cgid << endl;

    ret = shmctl(shmid, IPC_RMID, NULL);
    ERROR_CHECK(ret, -1, "shmctl");
    return 0;
}

另外,我们通常会使用 ipcs 命令来查看共享内存的使用:
Linux IPC进程间通信(二):共享内存_第1张图片

案例一:亲属进程间通信

父进程写入Hello, 子进程读

int test1()
{
    int shmid = shmget(IPC_PRIVATE, 1024, 0600);
    ERROR_CHECK(shmid, -1, "shmget");
    char* buf = (char*)shmat(shmid, NULL, 0);
    ERROR_CHECK(buf, (char*)-1, "shmat");
    
    if (fork() > 0)
    {
        strncpy(buf, "hello", 5);
        wait(NULL);
        int ret = shmctl(shmid, IPC_RMID, NULL);
        ERROR_CHECK(ret, -1, "shmctl");
        exit(0);
    }
    else
    {
        sleep(1);//等待父进程写完再读
        cout << "reading from shared memory:" << buf << endl; 
        exit(0);
    }
    return 0;
}

输出:
在这里插入图片描述


案例二:非亲属进程通信

写端 写入HelloWorld , 读端进行读取

reader.cpp:

int main()
{
    key_t key = ftok("file", 1);
    ERROR_CHECK(key, -1, "ftok");
    int shmid = shmget(key, 1024, 0600 | IPC_CREAT);
    ERROR_CHECK(shmid, -1, "shmget");
    char* buf = (char*)shmat(shmid, NULL, 0);
    ERROR_CHECK(buf, (char*)-1, "shmat");
    strncpy(buf, "Hello", 5);
    return 0;   
}

writer.cpp:

int main()
{
    key_t key = ftok("file", 1);
    ERROR_CHECK(key, -1, "ftok");
    int shmid = shmget(key, 1024, 0600);
    ERROR_CHECK(shmid, -1, "shmget");
    char* buf = (char*)shmat(shmid, NULL, 0);
    ERROR_CHECK(buf, (char*)-1, "shmat");
    cout << "reading from shared memory:" << buf << endl;
    int ret = shmctl(shmid, IPC_RMID, NULL);
    ERROR_CHECK(ret, -1, "shmctl");
    return 0;   
}

输出:
Linux IPC进程间通信(二):共享内存_第2张图片

你可能感兴趣的:(Linux)