进程间通讯——共享内存

来源:互联网 发布:中介软件哪个好 编辑:程序博客网 时间:2024/06/16 03:27

概念:

允许两个进程访问同一个逻辑地址;是在两个正在运行的进程之间传递数据的一种非常有效的方式。

 大多数的共享内存的具体实现,都把由不同进程之间共享的内存安排为同一段物理内存。

 共享内存是由IPC为进程创建的一个特殊的地址范围,它将出现在该进程的地址空间中。其他进程可以将同一段共享内存连接到他们自己的地址空间中。所有进程都可以访问共享内存中的地址,就好像他们是用malloc分配一样,如果某个进程向共享内存中写入了数据,所做的改动将立刻被可以访问同一段共享内存的其他进程看到。

如图:



 

    共享内存未提供同步机制需要用其他的机制来同步对共享内存的访问。

    用共享内存提供对大块内存区域的有效访问,同时通过传递小消息来同步对该内存的访问。

共享内存使用的函数:

 shmget函数:创建或获取函数

int shmget(key_t key,size_t size,intshmflg);

 

key:与信号量一样,程序员需要提供一个参数key,它有效地为共享内存段命名;shmget函数返回一个共享内存标识符,该标识符将用于后序的共享内存函数。

  有一个特殊的键值IPC_PRIVATE,它用于创建一个只属于创建进程的共享内存。但在有些Linux系统中,私有的共享内存其实并不是真正的私有。

第二个参数size以字节为单位指定需要共享的内存容量。

第三个参数shmflg包含9个比特的权限标志,它们的作用与创建文件时使用的mode编制一样。由IPC_CREAT定义的一个特殊比特必须和权限标志按位或才能创建一个新的共享内存段。与信号量的创建函数相似。

如果共享内存创建成功,该函数返回一个非负整数,即共享内存标识符,如果失败,返回-1。

shmat函数:

第一次创建共享内存段时,他不能被任何进程访问,想启用对该共享内存的访问,必须将其连接到一个进程的地址空间中。这就是shmat函数的作用;

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

shm_id是由shmget返回的共享内存标识符。

shm_addr指定的是共享内存连接到当前进程中的地址位置。他通常是一个空指针,表示让系统来选择共享内存出现的地址。

shmflg是一组标识符。他的两个可能取值是SHM_RND(这个标志与shn_addr联合使用,用来控制共享内存连接的地址)和SHM_RDONLY(它使得连接的内存只读)。让系统选择地址,降低程序对硬件的依耐性。

如果shmat调用成功,他返回一个指向共享内存第一个字节的指针,失败返回-1;


注意:

        共享内存的读写权限由它的属主(共享内存的创建者)、它的访问权限和当前进程的属主决定。

        但当shmflg&SHM_RDONLY为true时,此时即使该共享内存的访问权限允许写操作,他都不能被写入。

shmdt函数:

int shmdt(const void *shm_addr);

将共享内存从当前进程分离,参数是shmat返回的地址指针。成功返回0,失败返回-1。使当前进程不能使用该共享内存,而不是删除共享内存。

 

shmctl函数:

 

int shmtl(int shm_id,int command,struct shmid_ds *buf);

结构体shmid_ds:

struct shmid_ds{

         uid_tshm_perm.uid;

         uid_tshm_perm.gid;

mode_tshm_perm.mode;

}

shm_id是由shmget返回的共享内存标识符。

command是要采取的动作,它可以取三个值;

IPC_STAT         把shmid_ds结构中的数据设置为共享内存的当前关联值

IPC_SET  如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值

IPC_RMID删除共享内存段

buf是一个指针,它指向包含共享内存模式和访问权限的结构。

此函数成功返回0,失败返回-1;


注意:通常这个已被删除的处于连接状态的共享内存段还能继续使用,直到它从后一个进程中分离为止。但并没有在规范中定义删除一个正处于连接中的共享内存会出现的情况,故不要依赖它。