编程接口指南

System V 共享内存

在 SunOS 5.10 操作系统中,实现共享内存应用程序的最有效方法是依赖 mmap(2) 以及系统的本机虚拟内存功能。有关更多信息,请参见第 1 章,内存和 CPU 管理

SunOS 5.10 平台还支持 System V 共享内存,这是一种效率较低的将物理内存段附加到多个进程的虚拟地址空间的方法。 允许针对多个进程使用写入权限时,可以使用外部协议或机制(如信号量)防止出现不一致和冲突。

进程使用 shmget(2) 创建共享内存段。 还可以使用此调用获取现有共享段的 ID。 创建进程将以字节为单位设置此段的权限和大小。

共享内存段的初始属主可以使用 shmctl(2) 将拥有权指定给其他用户, 也可以撤消此指定。 其他具有适当权限的进程可以使用 shmctl(2) 在共享内存段上执行各种控制功能。

创建共享段之后,便可以使用 shmat(2) 将此段附加到进程地址空间。 可以使用 shmdt(2) 拆离此共享段。 附加进程必须具有相应的 shmat(2) 权限。 附加此段之后,进程便可以对其执行读写操作,如附加操作中请求的权限所允许的那样。 共享段可以由同一进程进行多次附加。

共享内存段由具有指向物理内存区域的唯一 ID 的控制结构说明。 此段的标识符称为 shmid。 可在 sys/shm.h 中找到共享内存段控制结构的结构定义。

访问共享内存段

shmget(2) 用于获取对共享内存段的访问。 当此调用成功时,便会返回共享内存段 ID (shmid)。 以下代码说明了 shmget(2)

#include  <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

...

 	key_t		key;			/* key to be passed to shmget() */

 	int		shmflg;		/* shmflg to be passed to shmget() */

 	int		shmid;		/* return value from shmget() */

 	size_t	size;			/* size to be passed to shmget() */

 	...

 	key = ...

 	size = ...

 	shmflg) = ...

 	if ((shmid = shmget (key, size, shmflg)) == –1) {

 		perror("shmget: shmget failed");

 		exit(1);

 	} else {

 		(void) fprintf(stderr,

 					"shmget: shmget returned %d\n", shmid);

 		exit(0);

 	}

 ...

控制共享内存段

shmctl(2) 用于更改共享内存段的权限和其他特性。 cmd 参数为以下控制命令之一。

SHM_LOCK

锁定内存中的指定共享内存段。 进程必须具有超级用户的有效 ID,才能执行此命令。

SHM_UNLOCK

解除锁定共享内存段。 进程必须具有超级用户的有效 ID,才能执行此命令。

IPC_STAT

返回控制结构中包含的状态信息,并将其放入 buf 指向的缓冲区中。 进程必须具有段的读取权限,才能执行此命令。

IPC_SET

设置有效的用户和组标识以及访问权限。 进程必须具有属主、创建者或超级用户的有效 ID,才能执行此命令。

IPC_RMID

删除共享内存段。 进程必须具有属主、创建者或超级用户的有效 ID,才能执行此命令。

 

 

以下代码说明了 shmctl(2)

#include			<sys/types.h>

#include			<sys/ipc.h>

#include			<sys/shm.h>

...

 int		cmd;		/* command code for shmctl() */

 int		shmid;	/* segment ID */

 struct shmid_ds	shmid_ds; /* shared memory data structure to

 									hold results */

 	...

 	shmid = ...

 	cmd = ...

 	if ((rtrn = shmctl(shmid, cmd, shmid_ds)) == –1) {

 		perror("shmctl: shmctl failed");

 		exit(1);

 	...

附加和拆离共享内存段

shmat()shmdt() 用于附加和拆离共享内存段(请参见 shmop(2) 手册页)。shmat(2) 返回指向共享段头的指针。shmdt(2) 可拆离位于 shmaddr 所指示的地址中的共享内存段。 以下代码说明了对 shmat(2)shmdt(2) 的调用。

#include			<sys/types.h>

#include			<sys/ipc.h>

#include			<sys/shm.h>



static struct state {	/* Internal record of attached segments. */

 	int		shmid;		/* shmid of attached segment */

 	char		*shmaddr;	/* attach point */

 	int		shmflg;		/* flags used on attach */

 	} ap[MAXnap];			/* State of current attached segments. */

 	int		nap;			/* Number of currently attached segments. */

 ...

 	char				*addr;			/* address work variable */

 	register int				i;			/* work area */

 	register struct state  *p;  /* ptr to current state entry */

 ...

 	p = &ap[nap++];

 	p–>shmid = ...

 	p–>shmaddr = ...

 	p–>shmflg = ...

 	p–>shmaddr = shmat(p->shmid, p->shmaddr, p->shmflg);

 	if(p–>shmaddr == (char *)-1) {

 		perror("shmat failed");

 		nap–-;

 	} else

 		 (void) fprintf(stderr, "shmop: shmat returned %p\n",

 					p–>shmaddr);

 	...

 	i = shmdt(addr);

 	if(i == –1) {

 		perror("shmdt failed");

 	} else {

 		(void) fprintf(stderr, "shmop: shmdt returned %d\n", i);

 		for (p = ap, i = nap; i–-; p++) {

 			if (p–>shmaddr == addr) *p = ap[–-nap];

 		}

 	}

 	...