Linux共享内存编程实例

原文链接:http://blog.csdn.net/pcliuguangtao/article/details/6526119

/*共享内存允许两个或多个进程进程共享同一块内存(这块内存会映射到各个进程自己独立的地址空间)
从而使得这些进程可以相互通信。
在GNU/Linux中所有的进程都有唯一的虚拟地址空间,而共享内存应用编程接口API允许一个进程使
用公共内存区段。但是对内存的共享访问其复杂度也相应增加。共享内存的优点是简易性。
使用消息队列时,一个进程要向队列中写入消息,这要引起从用户地址空间向内核地址空间的一次复制,
同样一个进程进行消息读取时也要进行一次复制。共享内存的优点是完全省去了这些操作。
共享内存会映射到进程的虚拟地址空间,进程对其可以直接访问,避免了数据的复制过程。
因此,共享内存是GNU/Linux现在可用的最快速的IPC机制。
进程退出时会自动和已经挂接的共享内存区段分离,但是仍建议当进程不再使用共享区段时
调用shmdt来卸载区段。
注意,当一个进程分支出父进程和子进程时,父进程先前创建的所有共享内存区段都会被子进程继承。
如果区段已经做了删除标记(在前面以IPC——RMID指令调用shmctl),而当前挂接数已经变为0,
这个区段就会被移除。
*/
/*
shmget( ) 创建一个新的共享内存区段
取得一个共享内存区段的描述符
shmctl( ) 取得一个共享内存区段的信息
为一个共享内存区段设置特定的信息
移除一个共享内存区段
shmat( ) 挂接一个共享内存区段
shmdt( ) 于一个共享内存区段的分离
*/
//创建一个共享内存区段,并显示其相关信息,然后删除该内存共享区
#include <stdio.h>
#include <unistd.h> //getpagesize( )
#include <sys/ipc.h>
#include <sys/shm.h>
#define MY_SHM_ID 67483
int main( )
{
//获得系统中页面的大小
printf( "page size=%d/n",getpagesize( ) );
//创建一个共享内存区段
int shmid,ret;
shmid=shmget( MY_SHM_ID,4096,0666|IPC_CREAT );
//创建了一个4KB大小共享内存区段。指定的大小必须是当前系统架构
//中页面大小的整数倍
if( shmid>0 )
printf( "Create a shared memory segment %d/n",shmid );
//获得一个内存区段的信息
struct shmid_ds shmds;
//shmid=shmget( MY_SHM_ID,0,0 );//示例怎样获得一个共享内存的标识符
ret=shmctl( shmid,IPC_STAT,&shmds );
if( ret==0 )
{
printf( "Size of memory segment is %d/n",shmds.shm_segsz );
printf( "Numbre of attaches %d/n",( int )shmds.shm_nattch );
}
else
{
printf( "shmctl( ) call failed/n" );
}
//删除该共享内存区
ret=shmctl( shmid,IPC_RMID,0 );
if( ret==0 )
printf( "Shared memory removed /n" );
else
printf( "Shared memory remove failed /n" );
return 0;
} //共享内存区段的挂载,脱离和使用
//理解共享内存区段就是一块大内存
#include <stdio.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <errno.h>
#define MY_SHM_ID 67483
int main( )
{
//共享内存区段的挂载和脱离
int shmid,ret;
void* mem;
shmid=shmget( MY_SHM_ID,0,0 );
if( shmid>=0 )
{
mem=shmat( shmid,( const void* )0,0 );
//shmat()返回进程地址空间中指向区段的指针
if( ( int )mem!=-1 )
{
printf( "Shared memory was attached in our address space at %p/n",mem );
//向共享区段内存写入数据
strcpy( ( char* )mem,"This is a test string./n" );
printf( "%s/n",(char*)mem );
//脱离共享内存区段
ret=shmdt( mem );
if( ret==0 )
printf( "Successfully detached memory /n" );
else
printf( "Memory detached failed %d/n",errno );
}
else
printf( "shmat( ) failed/n" ); }
else
printf( "shared memory segment not found/n" );
return 0;
}
/*内存共享区段与旗语和消息队列不同,一个区段可以被锁定。
被锁定的区段不允许被交换出内存。这样做的优势在于,与其
把内存区段交换到文件系统,在某个应用程序调用时再交换回内存,
不如让它一直处于内存中,且对多个应用程序可见。从提升性能的角度
来看,很重要的。
*/
int shmid;
//...
shmid=shmget( MY_SHM_ID,0,0 );
ret=shmctl( shmid,SHM_LOCK,0 );
if( ret==0 )
printf( "Locked!/n" );
////////////////////////////////////////////////////////////////////////
/*使用旗语协调共享内存的例子
使用和编译命令
gcc -Wall test.c -o test
./test create
./test use a &
./test use b &
./test read &
./test remove
*/
#include <stdio.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define MY_SHM_ID 34325
#define MY_SEM_ID 23234
#define MAX_STRING 200
typedef struct
{
int semID;
int counter;
char string[ MAX_STRING+1 ];
}MY_BLOCK_T;
int main(int argc,char** argv)
{
int shmid,ret,i;
MY_BLOCK_T* block;
struct sembuf sb;
char user;
//make sure there is a command
if( argc>=2 )
{
//create the shared memory segment and init it
//with the semaphore
if( !strncmp(argv[ 1 ],"create",6) )
{
//create the shared memory segment and semaphore
printf( "Creating the shared memory/n" );
shmid=shmget( MY_SHM_ID,sizeof( MY_BLOCK_T ),( IPC_CREAT|0666 ) );
block=( MY_BLOCK_T* )shmat( shmid,( const void* )0,0 );
block->counter=0;
//create the semaphore and init
block->semID=semget(MY_SEM_ID,1,( IPC_CREAT|0666 ));
sb.sem_num=0;
sb.sem_op=1;
sb.sem_flg=0;
semop( block->semID,&sb,1 );
//now detach the segment
shmdt( ( void* )block );
printf( "Create the shared memory and semaphore successuflly/n" ); }
else if( !strncmp(argv[ 1 ],"use",3) )
{
/*use the segment*/
//must specify also a letter to write to the buffer
if( argc<3 ) exit( -1 );
user=( char )argv[ 2 ][ 0 ];
//grab the segment
shmid=shmget( MY_SHM_ID,0,0 );
block=( MY_BLOCK_T* )shmat( shmid,( const void* )0,0 ); /*##########重点就是使用旗语对共享区的访问###########*/
for( i=0;i<100;++i )
{
sleep( 1 ); //设置成1s就会看到 a/b交替出现,为0则a和b连续出现
//grab the semaphore
sb.sem_num=0;
sb.sem_op=-1;
sb.sem_flg=0;
if( semop( block->semID,&sb,1 )!=-1 )
{
//write the letter to the segment buffer
//this is our CRITICAL SECTION
block->string[ block->counter++ ]=user; sb.sem_num=0;
sb.sem_op=1;
sb.sem_flg=0;
if( semop( block->semID,&sb,1 )==-1 )
printf( "Failed to release the semaphore/n" ); }
else
printf( "Failed to acquire the semaphore/n" );
} //do some clear work
ret=shmdt(( void*)block); }
else if( !strncmp(argv[ 1 ],"read",4) )
{
//here we will read the buffer in the shared segment
shmid=shmget( MY_SHM_ID,0,0 );
if( shmid!=-1 )
{
block=( MY_BLOCK_T* )shmat( shmid,( const void* )0,0 );
block->string[ block->counter+1 ]=0;
printf( "%s/n",block->string );
printf( "Length=%d/n",block->counter );
ret=shmdt( ( void*)block );
}
else
printf( "Unable to read segment/n" ); }
else if( !strncmp(argv[ 1 ],"remove",6) )
{
shmid=shmget( MY_SHM_ID,0,0 );
if( shmid>=0 )
{
block=( MY_BLOCK_T* )shmat( shmid,( const void* )0,0 );
//remove the semaphore
ret=semctl( block->semID,0,IPC_RMID );
if( ret==0 )
printf( "Successfully remove the semaphore /n" );
//remove the shared segment
ret=shmctl( shmid,IPC_RMID,0 );
if( ret==0 )
printf( "Successfully remove the segment /n" );
}
}
else
printf( "Unkonw command/n" );
}
return 0; }

Linux共享内存(二)的更多相关文章

  1. Linux 程序设计1:深入浅出 Linux 共享内存

    笔者最近在阅读Aerospike 论文时,发现了Aerospike是利用了Linux 共享内存机制来实现的存储索引快速重建的.这种方式比传统利用索引文件进行快速重启的方式大大提高了效率.(减少了磁盘 ...

  2. linux 共享内存shm_open实现进程间大数据交互

    linux 共享内存shm_open实现进程间大数据交互 read.c #include <sys/types.h> #include <sys/stat.h> #includ ...

  3. linux 共享内存

    共享内存是最高效的IPC机制,因为它不涉及进程之间的任何数据传输.这种高效带来的问题是,我们必须用其他手段来同步进程对共享内存的访问,否则会产生竞态条件.所以,共享内存通常和其他进程间通信方式一起使用 ...

  4. Linux共享内存(一)

    inux系统编程我一直看 <GNU/LINUX编程指南>,只是讲的太简单了,通常是书和网络上的资料结合着来掌握才比较全面 .在掌握了书上的内容后,再来都其他资料 . 原文链接 http:/ ...

  5. 【转载】ipcs与Linux共享内存

    一.共享内存相关知识 所谓共享内存,就是多个进程间共同地使用同一段物理内存空间,它是通过将同一段物理内存映射到不同进程的 虚拟空间来实现的.由于映射到不同进程的虚拟空间中,不同进程可以直接使用,不需要 ...

  6. Linux 共享内存 详解

    一.什么是共享内存区 共享内存区是最快的可用IPC形式.它允许多个不相关的进程去访问同一部分逻辑内存.如果需要在两个运行中的进程之间传输数据,共享内存将是一种效率极高的解决方案.一旦这样的内存区映射到 ...

  7. Linux共享内存使用常见陷阱与分析

    所谓共享内存就是使得多个进程可以访问同一块内存空间,是最快的可用IPC形式.是针对其他通信机制运行效率较低而设计的.往往与其它通信机制,如 信号量结合使用,来达到进程间的同步及互斥.其他进程能把同一段 ...

  8. linux 共享内存实现

    说起共享内存,一般来说会让人想起下面一些方法:1.多线程.线程之间的内存都是共享的.更确切的说,属于同一进程的线程使用的是同一个地址空间,而不是在不同地址空间之间进行内存共享:2.父子进程间的内存共享 ...

  9. Linux共享内存

    1.什么是共享内存在前面讲虚拟内存机制时,有讲到Linux的内存映射机制:初始化虚拟内存区域时,会把虚拟内存和磁盘文件对象对应起来.由于内存映射机制,一个磁盘文件对象可被多个进程共享访问,也可被多个进 ...

随机推荐

  1. 公钥加密算法那些事 | RSA 与 ECC 系统对比

    一.背景 据记载,公元前 400 年,古希腊人发明了置换密码.1881 年世界上的第一个电话保密专利出现.在第二次世界大战期间,德国军方启用「恩尼格玛」密码机,密码学在战争中起着非常重要的作用. 随着 ...

  2. HDU 4334 5-sum

    题目大意: 从5个集合中个选取一个数出来,使5个数相加之和为0 , 判断是否存在这种可能 因为集合数目最多200,那么200^3 = 8000000 , 那么这里很明显要把5个数拆成2个和3个计算,因 ...

  3. [luoguP1227] [JSOI2008]完美的对称(sort)

    传送门 排序! #include <cstdio> #include <iostream> #include <algorithm> #define N 20001 ...

  4. hdu 4422

    #include<stdio.h> #include<string.h> #define inf  0x7fffffff int main() {     int i,j,k, ...

  5. bzoj 3786 星系探索 dfs+splay

    [BZOJ3786]星系探索 Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球 ...

  6. idea web项目启动失败的情况---webapp文件夹路径不对,应如图位置

  7. xth 砍树(codevs 1369)

    题目描述 Description 在一个凉爽的夏夜,xth 和 rabbit 来到花园里砍树.为啥米要砍树呢?是这样滴,小菜儿的儿子窄森要出生了.Xth这个做伯伯的自然要做点什么.于是他决定带着rab ...

  8. HDU 6076 (动态规划)

    HDU 6076 Security Check Problem : 有两个长度为n的队列过安检,每个人有一个特征值.如果两个队列中的第一个人的特征值之差小于等于k,那么一次只能检查其中一个人,否则一次 ...

  9. 使用Navicat进行数据库对比同步

    使用Navicat进行数据库对比同步 当有多个数据库时,有时会出现结构或者数据不同步的问题,这时候可以使用navivat工具对比同步( 我的Navicat版本是11.0.17). 参考博客: 岁伏的博 ...

  10. java内存区域和对象的产生

    一直被java中内存组成弄的头晕眼花,这里总结下都有哪些,先上图片 程序计数器 小块内存,线程执行字节码的信号指示器,以此获取下一条需要执行的字节码指令,分支,循环,跳转,异常处理,线程恢复都要依赖他 ...