分享
 
 
 

共享内存

王朝百科·作者佚名  2009-11-13
窄屏简体版  字體: |||超大  

共享内存指在多处理器的计算机系统中,可以被不同中央处理器(CPU)访问的大容量内存。由于多个CPU需要快速访问存储器,这样就要对存储器进行缓存(Cache)。任何一个缓存的数据被更新后,由于其他处理器也可能要存取,共享内存就需要立即更新,否则不同的处理器可能用到不同的数据

共享内存 (shared memory)是 Unix下的多进程之间的通信方法 ,这种方法通常用于一个程序的多进程间通信,实际上多个程序间也可以通过共享内存来传递信息。

共享内存的创建

共享内存是存在于内核级别的一种资源,在shell中可以使用ipcs命令来查看当前系统IPC中的状态,在文件系统/proc目录下有对其描述的相应文件。函数shmget可以创建或打开一块共享内存区。函数原型如下:

#include <sys/shm.h>

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

函数中参数key用来变换成一个标识符,而且每一个IPC对象与一个key相对应。当新建一个共享内存段时,size参数为要请求的内存长度(以字节为单位)。

注意:内核是以页为单位分配内存,当size参数的值不是系统内存页长的整数倍时,系统会分配给进程最小的可以满足size长的页数,但是最后一页的剩余部分内存是不可用的。

当打开一个内存段时,参数size的值为0。参数flag中的相应权限位初始化ipc_perm结构体中的mode域。同时参数flag是函数行为参数,它指定一些当函数遇到阻塞或其他情况时应做出的反应。shmid_ds结构初始化如表14-4所示。

表14-4 shmid_ds的初始化

shmid_ds结构数据

初 值

shmid_ds结构数据

初 值

shm_lpid

0

shm_dtime

0

shm_nattach

0

shm_ctime

系统当前值

shm_atime

0

shm_segsz

参数 size

下面实例演示了使用shmget函数创建一块共享内存。程序中在调用shmget函数时指定key参数值为IPC_PRIVATE,这个参数的意义是创建一个新的共享内存区,当创建成功后使用shell命令ipcs来显示目前系统下共享内存的状态。命令参数-m为只显示共享内存的状态。

(1)在vi编辑器中编辑该程序如下:

程序清单14-8 create_shm.c 使用shmget函数创建共享内存

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

#include <stdlib.h>

#include <stdio.h>

#define BUFSZ 4096

int main ( void )

{

int shm_id; /*共享内存标识符*/

shm_id=shmget(IPC_PRIVATE, BUFSZ, 0666 ) ;

if (shm_id < 0 ) { /*创建共享内存*/

perror( "shmget" ) ;

exit ( 1 );

}

printf ( "successfully created segment : %d

", shm_id ) ;

system( "ipcs -m"); /*调用ipcs命令查看IPC*/

exit( 0 );

}

(2)在shell中编译该程序如下:

$gcc create_shm.c–o create_shm

(3)在shell中运行该程序如下:

$./ create_shm

successfully created segment : 2752516

------ Shared Memory Segments --------

key shmid owner perms bytes nattch status

0x00000000 65536 root 600 393216 2 dest

0x00000000 2654209 root 666 4096 0

0x0056a4d5 2686978 root 600 488 1

0x0056a4d6 2719747 root 600 131072 1

0x00000000 2752516 root 666 4096 0

上述程序中使用shmget函数来创建一段共享内存,并在结束前调用了系统shell命令ipcs –m来查看当前系统IPC状态。

共享内存的操作

由于共享内存这一特殊的资源类型,使它不同于普通的文件,因此,系统需要为其提供专有的操作函数,而这无疑增加了程序员开发的难度(需要记忆额外的专有函数)。使用函数shmctl可以对共享内存段进行多种操作,其函数原型如下:

#include <sys/shm.h>

int shmctl( int shm_id, int cmd, struct shmid_ds *buf );

函数中参数sh_mid为所要操作的共享内存段的标识符,struct shmid_ds型指针参数buf的作用与参数cmd的值相关,参数cmd指明了所要进行的操作,其解释如表14-5所示。

表14-5 shmctl函数中参数 cmd详解

cmd的值

意 义

IPC_STAT

取shm_id所指向内存共享段的shmid_ds结构,对参数buf指向的结构赋值

IPC_SET

使用buf指向的结构对sh_mid段的相关结构赋值,只对以下几个域有作用,shm_perm.

uid shm_perm.gid以及shm_perm.mode

注意此命令只有具备以下条件的进程才可以请求:

1.进程的用户ID等于shm_perm.cuid或者等于shm_perm.uid

2.超级用户特权进程

IPC_RMID

删除shm_id所指向的共享内存段,只有当shmid_ds结构的shm_nattch域为零时,才会真正执行删除命令,否则不会删除该段

注意此命令的请求规则与IPC_SET命令相同

SHM_LOCK

锁定共享内存段在内存,此命令只能由超级用户请求

SHM_UNLOCK

对共享内存段解锁,此命令只能由超级用户请求

使用函数shmat将一个存在的共享内存段连接到本进程空间,其函数原型如下:

#include <sys/shm.h>

void *shmat( int shm_id, const void *addr, int flag );

函数中参数shm_id指定要引入的共享内存,参数addr与flag组合说明要引入的地址值,通常只有2种用法,addr为0,表明让内核来决定第1个可以引入的位置。addr非零,并且flag中指定SHM_RND,则此段引入到addr所指向的位置(此操作不推荐使用,因为不会只对一种硬件上运行应用程序,为了程序的通用性推荐使用第1种方法),在flag参数中可以指定要引入的方式(读写方式指定)。

%说明:函数成功执行返回值为实际引入的地址,失败返回–1。shmat函数成功执行会将shm_id段的shmid_ds结构的shm_nattch计数器的值加1。

当对共享内存段操作结束时,应调用shmdt函数,作用是将指定的共享内存段从当前进程空间中脱离出去。函数原型如下:

#include <sys/shm.h>

int shmdt( void *addr);

参数addr是调用shmat函数的返回值,函数执行成功返回0,并将该共享内存的shmid_ds结构的shm_nattch计数器减1,失败返回–1。

下面实例演示了操作共享内存段的流程。程序的开始部分先检测用户是否有输入,如出错则打印该命令的使用帮助。接下来从命令行读取将要引入的共享内存ID,使用shmat函数引入该共享内存,并在分离该内存之前睡眠3秒以方便查看系统IPC状态。

(1)在vi编辑器中编辑该程序如下:

程序清单14-9 opr_shm.c 操作共享内存段

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

#include <stdlib.h>

#include <stdio.h>

int main ( int argc, char *argv[] )

{

int shm_id ;

char * shm_buf;

if ( argc != 2 ){ /* 命令行参数错误 */

printf ( "USAGE: atshm <identifier>" ); /*打印帮助消息*/

exit (1 );

}

shm_id = atoi(argv[1]); /*得到要引入的共享内存段*/

/*引入共享内存段,由内核选择要引入的位置*/

if ( (shm_buf = shmat( shm_id, 0, 0)) < (char *) 0 ){

perror ( "shmat" );

exit (1);

}

printf ( " segment attached at %p

", shm_buf ); /*输出导入的位置*/

system("ipcs -m");

sleep(3); /* 休眠 */

if ( (shmdt(shm_buf)) < 0 ) { /*与导入的共享内存段分离*/

perror ( "shmdt");

exit(1);

}

printf ( "segment detached

" );

system ( "ipcs -m " ); /*再次查看系统IPC状态*/

exit ( 0 );

}

(2)在shell中编译该程序如下:

$gcc opr_shm.c–o opr_shm

(3)在shell中运行该程序如下:

$./ opr_shm 2752516

segment attached at 0xb7f29000

------ Shared Memory Segments --------

key shmid owner perms bytes nattch status

0x00000000 65536 root 600 393216 2 dest

0x00000000 2654209 root 666 4096 0

0x0056a4d5 2686978 root 600 488 1

0x0056a4d6 2719747 root 600 131072 1

0x00000000 2752516 root 666 4096 1

segment detached

------ Shared Memory Segments --------

key shmid owner perms bytes nattch status

0x00000000 65536 root 600 393216 2 dest

0x00000000 2654209 root 666 4096 0

0x0056a4d5 2686978 root 600 488 1

0x0056a4d6 2719747 root 600 131072 1

0x00000000 2752516 root 666 4096 0

上述程序中从命令行中读取所要引入的共享内存ID,并使用shmat函数引入该内存到当前的进程空间中。注意在使用shmat函数时,将参数addr的值设为0,所表达的意义是由内核来决定该共享内存在当前进程中的位置。由于在编程的过程中,很少会针对某一个特定的硬件或系统编程,所以由内核决定引入位置也就是shmat推荐的使用方式。在导入后使用shell命令ipcs –m来显示当前的系统IPC的状态,可以看出输出信息中nattch字段为该共享内存时的引用值,最后使用shmdt函数分离该共享内存并打印系统IPC的状态。

共享内存使用注意事项

共享内存相比其他几种方式有着更方便的数据控制能力,数据在读写过程中会更透明。当成功导入一块共享内存后,它只是相当于一个字符串指针来指向一块内存,在当前进程下用户可以随意的访问。缺点是,数据写入进程或数据读出进程中,需要附加的数据结构控制,共享内存通信数据结构示意如图14-9所示。

图14-9 共享内存通信数据结构示意

%说明:图中两个进程同时遵循一定的规则来读写该内存。同时,在多进程同步或互斥上也需要附加的代码来辅助共享内存机制。

在共享内存段中都是以字符串的默认结束符为一条信息的结尾。每个进程在读写时都遵守这个规则,就不会破坏数据的完整性。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有