您的位置:

Linux中共享内存函数shmget的使用指南

一、shmget函数介绍

shmget函数是Linux中用于创建共享内存的函数,其定义如下:

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

int shmget(key_t key, size_t size, int shmflg);

shmget函数的三个参数分别是key、size以及shmflg。

二、key参数详解

key参数用于指定共享内存的唯一标识符。它可以是由ftok函数生成的标识符,也可以是在共享内存创建之前由IPC_PRIVATE指定的私有标识符。

ftok函数的定义如下:

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

key_t ftok(const char *pathname, int proj_id);

ftok函数会根据pathname参数和proj_id参数生成一个标识符,用于唯一标识一个共享内存对象。

例如,在以下示例中,我们创建了一个key用于共享内存:

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

#define SHM_SIZE 1024

int main()
{
    key_t key;
    int shmid;
    char *shm, *s;

    key = ftok(".", 'a');   //生成key

    shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666);    //创建共享内存

    if (shmid == -1) {
        perror("shmget");
        return 1;
    }

    return 0;
}

在上述示例中,我们使用ftok函数生成了一个key以便创建共享内存。

三、size参数详解

size参数用于指定要创建的共享内存的大小。

例如,在以下示例中,我们创建了一个大小为1024字节的共享内存:

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

#define SHM_SIZE 1024

int main()
{
    key_t key;
    int shmid;
    char *shm, *s;

    key = ftok(".", 'a');

    shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666);   //创建大小为1024字节的共享内存

    if (shmid == -1) {
        perror("shmget");
        return 1;
    }

    return 0;

}

四、shmflg参数详解

shmflg参数用于指定共享内存的访问权限和控制选项。它的值可以是以下常量的或运算结果:

  • IPC_CREAT:如果共享内存不存在,则创建共享内存
  • IPC_EXCL:如果共享内存已存在,则创建失败
  • IPC_NOWAIT:如果创建共享内存失败,则立即返回错误
  • 0666:指定共享内存的访问权限

例如,在以下示例中,我们创建了一个权限为0666,大小为1024字节的共享内存:

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

#define SHM_SIZE 1024

int main()
{
    key_t key;
    int shmid;
    char *shm, *s;

    key = ftok(".", 'a');

    shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666);   //创建权限为0666,大小为1024字节的共享内存

    if (shmid == -1) {
        perror("shmget");
        return 1;
    }

    return 0;
}

五、使用共享内存

创建完共享内存之后,我们就可以通过shmat函数将它附加到进程的地址空间,并进行读写操作了。

shmat函数的定义如下:

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

void *shmat(int shmid, const void *shmaddr, int shmflg);

例如,在以下示例中,我们创建了一个共享内存,然后将其附加到进程的地址空间,并写入了一些数据:

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

#define SHM_SIZE 1024

int main()
{
    key_t key;
    int shmid;
    char *shm, *s;

    key = ftok(".", 'a');

    shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666);   //创建共享内存

    if (shmid == -1) {
        perror("shmget");
        return 1;
    }

    shm = shmat(shmid, NULL, 0);    //将共享内存附加到进程地址空间

    if (shm == (char *) -1) {
        perror("shmat");
        return 1;
    }

    strcpy(shm, "hello, world");    //在共享内存中写入数据

    return 0;
}

六、删除共享内存

当我们不再需要使用共享内存时,需要使用shmctl函数将其从系统中删除。

shmctl函数的定义如下:

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

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

要删除共享内存,需要先将其从进程地址空间中分离,然后调用shmctl函数将其删除。例如,以下示例展示了如何删除前面创建的共享内存:

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

#define SHM_SIZE 1024

int main()
{
    key_t key;
    int shmid;
    char *shm, *s;
    struct shmid_ds shmds;

    key = ftok(".", 'a');

    shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666);  //创建共享内存

    if (shmid == -1) {
        perror("shmget");
        return 1;
    }

    shm = shmat(shmid, NULL, 0);   //将共享内存附加到进程地址空间

    if (shm == (char *) -1) {
        perror("shmat");
        return 1;
    }

    strcpy(shm, "hello, world");   //在共享内存中写入数据

    shmdt(shm);   //将共享内存从进程地址空间中分离

    shmctl(shmid, IPC_RMID, &shmds);   //删除共享内存

    return 0;
}

七、小结

本文从key、size和shmflg三个参数的介绍入手,对shmget函数做了详细的讲解,并通过代码示例阐述了共享内存的创建、写入、读取和删除等操作。在实际开发中,共享内存作为一种高效的进程间通信方式,可以有效地提高程序的性能和并发能力。