System V 共享内存区

24 篇文章 0 订阅
System V共享内存区在概念上类似于Posix共享内存区。代之以调用shm_open后调用mmap的是,先调用shmget,再调用shmat函数。
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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值