Chinaunix首页 | 论坛 | 博客
  • 博客访问: 218568
  • 博文数量: 71
  • 博客积分: 1420
  • 博客等级: 上尉
  • 技术积分: 952
  • 用 户 组: 普通用户
  • 注册时间: 2008-01-11 14:26
文章存档

2009年(16)

2008年(55)

我的朋友

分类: LINUX

2008-04-16 09:36:45

一、什么是共享内存区

共享内存区是最快的可用IPC形式。它允许多个不相关的进程去访问同一部分逻辑内存。如果需要在两个运行中的进程之间传输数据,共享内存将是一种效率极高的解决方案。一旦这样的内存区映射到共享它的进程的地址空间,这些进程间数据的传输就不再涉及内核。这样就可以减少系统调用时间,提高程序效率。

共享内存是由IPC为一个进程创建的一个特殊的地址范围,它将出现在进程的地址空间中。其他进程可以把同一段共享内存段“连接到”它们自己的地址空间里去。所有进程都可以访问共享内存中的地址。如果一个进程向这段共享内存写了数据,所做的改动会立刻被有访问同一段共享内存的其他进程看到。

要注意的是共享内存本身没有提供任何同步功能。也就是说,在第一个进程结束对共享内存的写操作之前,并没有什么自动功能能够预防第二个进程开始对它进行读操作。共享内存的访问同步问题必须由程序员负责。可选的同步方式有互斥锁、条件变量、读写锁、纪录锁、信号灯。

       共享内存区分为System V共享内存区和Posix共享内存区。本节介绍System V共享内存区。

 

二、共享内存区结构

       和其他XSI IPC一样,内核为每个共享存储段设置一个shmid_ds结构。

       struct shmid_ds{

              struct ipc_perm      shm_perm;     /*operation perms*/

              int                         shm_segez;     /*size of segment*/

              time_t                   shm_atime;     /*last attach time*/

              time_t                   shm_dtime;     /*last detach time*/

              time_t                   shm_ctime;     /*last change time*/

              unsigned short              shm_lpid;       /*pid of creator*/

              unsigned short       shm_cpid;      /*pid of last operator*/

              short                     shm_nattch;    /*no.of current attaches*/

…….

       };

其中ipc_perm是我们在XSI IPC里介绍的权限结构。

struct ipc_perm{

       key_t      key;

       ushort     uid;  /*owner euid and egid*/

       ushort     gid;

       ushort     cuid; /*creator euid and egid*/

       ushort     cgid;

       ushort     mode; /*lower 9 bits of shmflg*/

       ushort     seq;  /*sequence number*/

};

 

三、共享内存区函数

       shmget函数创建一个尚未存在的共享内存区,或者访问一个已存在的共享内存区。

1

名称:

shmget

功能

获得一个共享存储标识符

头文件

#inlcude

#include

函数原形

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

参数:

ket

size 内存区大小

shmflg 权限值

返回值:

若成功则返回共享内存id,若出错则为-1

     

 

 

 

 

 

 

  key为共享存储的外部键,通过ftok获得。参数size是该共享存储段的长度。如果正在创建一个新段,则必须指定其size。如果正在引用一个现存的段,则将size指定为0。当创建一新段时,段内的内容初始化为0shmflg由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的。当需要创建新的共享内存段时需要与IPC_CREAT标志按位或。设置IPC_CREAT标志并传递已存在的共享内存段不会产生错误。如果想创建一个读一无二的共享内存区可以与IPC_CREAT|IPC_EXCL按位或,这样如果系统以存在这个共享内存区,shmget函数就会报错。

下面是一个创建共享内存区的例子;

/*shmget.c创建共享内存区*/

#include

#include

#include

 

int main(int argc,char **argv)

{

int c,id,oflag;

char *ptr;

size_t length;

oflag=0644|IPC_CREAT;

 

if(argc!=3)

{

    printf(“usage:shmget \n”);

    exit(1);

}

 

length=atoi(argv[2]);

id=shmget(ftok(argv[1],0),length,oflag);

printf(“shm_id: %d\n”,id);

exit(0);

}

运行结果为:

#cc –o shmget shmget.c

#./shmget test 100

shm_id262147

       System V共享内存区至少具有随内核持续性,因此程序结束该共享内存区还存在。

 

在共享内存段刚被创建的时候,任何进程还都不能访问它。为了建立这个共享内存段的访问渠道,必须由我们来把它连接到某个进程的地址空间。这项工作是由shmat函数完成的。

2

名称:

shmat

功能:

将共享内存段连接到他的地址空间

头文件:

#include

#inlcude

函数原形:

void *shmat(int shm_id,void *shm_addr,int shmflg);

参数:

shm_id 标识码

shm_addr 连接到的地址

shmflg  标志位

返回值:

若成功则为指向共享存储的指针,若出错则为-1

      

 

 

 

 

 

 shm_idshmget返回的共享内存标识码。

       shm_addr是把共享内存连接到当前进程去的时候准备放置它的那个地址。这通常是一个空指针,表示把选择共享内存出现处的地址这项工作交给系统去完成。

       shmflg是一组按位或的标志。它的两个可能值是SHM_RND(这个标志与shm_addr一起控制着共享连接的地址)SHM_RDONLY(它使连接的共享内存成为一个只读区间)。很少有需要控制共享内存连接的地址的情况,一般都是由系统替你挑选一个地址,否则就会使你的软件对硬件的依赖性过高。

       shmat的返回值是该段所连接的实际地址,如果出错则返回-1。如果shmat成功执行,那么内核将该共享存储段shmid_ds结构的shm_nattch计算器加1

       缺省情况下,只要调用进程具有某个共享内存区的读写权限,它附接该内存区后就能够同时读写该内存区。只有flag参数指定SHM_RDONLY值时,它以只读方式访问。

 

当一个进程完成某个共享内存区的使用时,它可调用shmdt函数脱离与这个共享内存区的联系。

3

名称:

shmdt

功能:

脱接共享存储段

头文件:

#include

#inlcude

函数原形:

int shmdt(void *shmaddr);

参数:

shmaddr

返回值:

若成功则为0,若出错则为-1

      

 

 

当一个进程终止时,它的所有当前附接着的共享内存区都自动断接掉。注意本函数调用并不是从系统中删除其标识符以及其数据结构。该标识符仍然存在,直至某个进程调用shmctl特地删除它。

       addr参数是以前调用shmat时的返回值。如果成功,shmdt将使相关shmid_ds结构中的shm_nattch计数其减1

阅读(730) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~