System V共享内存区在概念上类似于Posix共享内存区。代之以调用shm_open后调用mmap的是,先调用shmget,再调用shmat函数。
shmget函数创建一个尚未存在的共享内存区,或者访问一个已经存在的共享内存区。
key既可以是ftok函数的返回值,也可以是IPC_PRIVATE(大多数实现定义该值为0);
size指定内存的大小,且新建的共享内存区的所有字节被初始化为0;若访问一个已存在的共享内存区,则size值应为0;
oflag位读写权限的组合值。还可以与IPC_CREAT或IPC_CREAT | IPC_EXCL按位或;
shmat函数返回值为所指定的共享内存区在调用进程内的起始地址,该值规则如下:
*) 如果shmaddr地址为NULL,则系统替调用者选择地址,也是推荐的方式;
*) 若shmaddr为非空指针,那么返回地址取决于调用者是否给flag参数指定了SHM_RND值:
*) 如果没有SHM_RND指定,那么相应的共享内存区附接到由shmaddr参数指定的地址;
*) 如果SHM_RND指定了,那么相应的共享内存区附接到由shmaddr指定的地址向下舍入一个SHMLBA常值。LBA代表"低端边界地址"。
flag参数中也可以指定SHM_RDONLY值,指定为只读。
当一个进程完成某个共享内存区的使用时,它可以调用shmdt断接这个内存区.
shmctl提供了对一个共享内存区的多种操作:
IPC_RMID 从系统中删除由shmid标识的共享内存区并删除它;
IPC_SET 给所指定的共享内存区设置其shmid_ds结构中的以下三个成员:shm_perm.uid,shem_perm.gid和shm_perm.mode,它们的值来自由buff参数指向的结构中的相应成员。
IPC_STAT (通常为buff参数)向调用者返回所指定共享内存区的当前shmid_ds结构。
其中,shmid_ds结构为:
shmget函数创建一个尚未存在的共享内存区,或者访问一个已经存在的共享内存区。
#include <sys/shm.h>
int shmget(key_t key, size_t size, int oflag);
返回值为共享内存区的标识符。
key既可以是ftok函数的返回值,也可以是IPC_PRIVATE(大多数实现定义该值为0);
size指定内存的大小,且新建的共享内存区的所有字节被初始化为0;若访问一个已存在的共享内存区,则size值应为0;
oflag位读写权限的组合值。还可以与IPC_CREAT或IPC_CREAT | IPC_EXCL按位或;
void *shmat(int shmid, const void *shmaddr, int flag);
shmid为shmget函数返回的标识符;
shmat函数返回值为所指定的共享内存区在调用进程内的起始地址,该值规则如下:
*) 如果shmaddr地址为NULL,则系统替调用者选择地址,也是推荐的方式;
*) 若shmaddr为非空指针,那么返回地址取决于调用者是否给flag参数指定了SHM_RND值:
*) 如果没有SHM_RND指定,那么相应的共享内存区附接到由shmaddr参数指定的地址;
*) 如果SHM_RND指定了,那么相应的共享内存区附接到由shmaddr指定的地址向下舍入一个SHMLBA常值。LBA代表"低端边界地址"。
flag参数中也可以指定SHM_RDONLY值,指定为只读。
当一个进程完成某个共享内存区的使用时,它可以调用shmdt断接这个内存区.
int shmdt(const void *shmaddr);
shmaddr为进程内共享内存区的首地址。
shmctl提供了对一个共享内存区的多种操作:
int shmctl(int shmid, int cmd, struct shmid_ds *buff);
该函数提供以下三个命令:
IPC_RMID 从系统中删除由shmid标识的共享内存区并删除它;
IPC_SET 给所指定的共享内存区设置其shmid_ds结构中的以下三个成员:shm_perm.uid,shem_perm.gid和shm_perm.mode,它们的值来自由buff参数指向的结构中的相应成员。
IPC_STAT (通常为buff参数)向调用者返回所指定共享内存区的当前shmid_ds结构。
其中,shmid_ds结构为:
struct shmid_ds
{
struct ipc_perm shm_perm; // operation permission struct
size_t shm_segsz; // segment size共享内存区大小,以字节为单位
pid_t shm_ipid; // pid of last operation
pid_t shm_cpid; // creator pid
shmatt_t shm_nattch; // current # attatched
shamat_t shm_cnattch; // in-core # attached
time_t shm_atime; // last attach time
time_t shm_dtime; // last detach time
time_t shm_ctime; // last change time of this structure
};
// shmget.c
#include <sys/shm.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#define SVSHM_MODE 0644
int main(int argc, char **argv)
{
int c, id, oflag;
char *ptr;
size_t length;
oflag = SVSHM_MODE | IPC_CREAT;
while((c = getopt(argc, argv, "e")) != -1)
{
switch(c)
{
case 'e':
oflag |= IPC_EXCL;
break;
}
printf("optind = %d\n", optind);
}
if(optind != argc - 2)
{
perror("usage: ./shmget [-e] <pathname> <length>");
exit(0);
}
length = atoi(argv[optind + 1]);
id = shmget(ftok(argv[optind], 0), length, oflag);
ptr = shmat(id, NULL, 0);
return 0;
}
// shmread.c
#include <sys/shm.h>
#include <stdlib.h>
#include <stdio.h>
#define SVSHM_MODE 0644
int main(int argc, char **argv)
{
int i, id;
struct shmid_ds buff;
unsigned char c, *ptr;
if(argc != 2)
{
perror("usage: ./shmread <pathname>");
exit(0);
}
id = shmget(ftok(argv[1], 0), 0, SVSHM_MODE);
ptr = shmat(id, NULL, 0);
shmctl(id, IPC_STAT, &buff);
for(i = 0; i < buff.shm_segsz; i++)
if((c = *ptr++) == (i % 256))
{
printf("ptr[%d] = %d", i, c);
}
return 0;
}
// shmrmid.c
#include <stdlib.h>
#include <sys/shm.h>
#define SVSHM_MODE 0644
int main(int argc, char **argv)
{
int id;
if(argc != 2)
{
perror("usage: ./shmrmid <pathname>");
exit(0);
}
id = shmget(ftok(argv[1], 0), 0, SVSHM_MODE);
shmctl(id, IPC_RMID, NULL);
return 0;
}
// shmwrite.c
#include <sys/shm.h>
#include <stdlib.h>
#define SVSHM_MODE 0644
int main(int argc, char **argv)
{
int i, id;
struct shmid_ds buff;
unsigned char *ptr;
if(argc != 2)
{
perror("usage: ./shmwrite <pathname>");
exit(0);
}
id = shmget(ftok(argv[1], 0), 0, SVSHM_MODE);
ptr = shmat(id, NULL, 0);
shmctl(id, IPC_STAT, &buff);
for(i = 0; i < buff.shm_segsz; i++)
*ptr++ = i % 256;
return 0;
}
[test@ localhost] ./shmget info 1234 #指定共享内存区大小为1234个字节
[test@ localhost] ./ipc -m #查看共享内存区信息
[test@ localhost] ./shmwrite info
[test@ localhost] ./shmread info