一、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函数做了详细的讲解,并通过代码示例阐述了共享内存的创建、写入、读取和删除等操作。在实际开发中,共享内存作为一种高效的进程间通信方式,可以有效地提高程序的性能和并发能力。