·ChinaUnix首页 ·论坛 ·博客 
Linux首页 | Linux新闻 | Linux文档 | Linux论坛 | Linux下载 | Linux博客 | Linux搜索
新手入门 | 安装启动 | 管理员指南 | 开发手册 | 桌面应用 | 程序开发 | 数据库 | 网络技术| CentOS | Fedora | MySQL | Apache | Ubuntu | Gentoo| OSCON08
  Linux时代 >> 技术文档 >> 程序开发
 
用共享内存方法实现进程之间的通讯
来源: ChinaUnix博客  日期: 2008.07.24 13:16 (共有条评论) 我要评论
 
在两个进程间共享数据的方法,至今为止我们只说过利用管道。管道只是利用了输入输出重定向的原理,非常简单。而且只能在父子进程间使用。很多场合下这种方法是无法满足我们的要求的。
那么现在,我们又有了一种新的方法——利用共享内存(shared memory)。这可以使我们在任意两个进程间传递数据,而且也是相对简单容易实现的一个方法。
注意:在正常情况下,一个进程的所使用的内存区是不允许其它进程访问的。这里我们要开辟的共享内存是例外。
我们来做一个简单的剪贴板。从标准输入向mcut输入数据,mcut将其放在共享内存中,然后mpaste从共享内存中读出数据并显示。
/*      mcut.c  */
#include
#include
#include
#include
int     main()
{
        key_t   shmkey;
        int     shmid , in_tmp ;
        char    *head , *pos ,
                in_data[4096] , *in_ptr ;
        shmkey = ftok( "mcut" , 'a' );          //      计算标识符
        //      shmid开辟共享内存
        shmid = shmget( shmkey , sizeof(in_data) , IPC_CREAT | 0666 ) ;
        head = pos = shmat( shmid , 0 , 0 );    //      允许本进程使用这块共享内存
        in_ptr = in_data ;
        //      开始从标准输入输入数据,暂时存在in_data里。
        while( (in_tmp=getchar()) != EOF )
        {
                *in_ptr = in_tmp ;
                in_ptr++ ;
        }
        
        *in_ptr = '\0' ;
        in_ptr = in_data ;
        //      开始写入共享内存
        while( *in_ptr != '\0' )
        {
                *pos = *in_ptr ;
                pos++;
                in_ptr++;
        }
        *pos = '\0' ;
        shmdt( head );          //      禁止本进程使用这块内存
        return 0;
}
/*      mpaste.c        */
#include
#include
#include
#include
int     main()
{
        key_t   shmkey;
        int     shmid;
        char    *head , *pos ,
                out_data[4096] , *out_ptr ;
        
        shmkey = ftok( "mcut" , 'a' );          //      计算标识符
        //      开辟共享内存
        shmid = shmget( shmkey , sizeof(out_data) , IPC_ALLOC | 0666 );
        head = pos = shmat( shmid , 0 , 0 );    //      允许本进程使用这块共享内存
        out_ptr = out_data ;
        
        //      从共享内存中取得数据
        while( *pos != '\0' )
        {
                *out_ptr = *pos ;
                out_ptr++ ;
                pos++ ;
        }
        *out_ptr = '\0' ;
        printf( "%s\n" , out_data );
        fflush( stdout );
        shmdt( head );          //      禁止本进程使用这块共享内存
        return 0;
}
如何?明白多少了?
要使用共享内存,应该有如下步骤:
1.开辟一块共享内存      shmget()
2.允许本进程使用共某块共享内存  shmat()
3.写入/读出
4.禁止本进程使用这块共享内存    shmdt()
5.删除这块共享内存      shmctl()或者命令行下ipcrm
上面的程序中用到了如下函数,我们一一解释一下。
首先是ftok()。它有两个参数,一个是字符串,一个是字符。字符串一般用当前进程的程序名,字符一般用来标记这个标识符所标识的共享内存是这个进程所开辟的第几个共享内存。ftok()会返回一个key_t型的值,也就是计算出来的标识符的值。
其次,操作共享内存,我们用到了下面的函数
#include
#include
#include
int     shmget( key_t shmkey , int shmsiz , int flag );
void    *shmat( int shmid , char *shmaddr , int shmflag );
int     shmdt( char *shmaddr );
shmget()是用来开辟/指向一块共享内存的函数。参数定义如下:
key_t shmkey 是这块共享内存的标识符。如果是父子关系的进程间通信的话,这个标识符用IPC_PRIVATE来代替。但是刚才我们的两个进程没有任何关系,所以就用ftok()算出来一个标识符使用了。
int shmsiz 是这块内存的大小.
int flag 是这块内存的模式(mode)以及权限标识(关于权限的意思,请参阅本系列第五章)。
模式可取如下值:        新建:IPC_CREAT
                        使用已开辟的内存:IPC_ALLOC
                        如果标识符以存在,则返回错误值:IPC_EXCL
然后将“模式” 和“权限标识”进行“或”运算,做为第三个参数。
如:    IPC_CREAT | IPC_EXCL | 0666
这个函数成功时返回共享内存的ID,失败时返回-1。
shmat()是用来允许本进程访问一块共享内存的函数。
int shmid是那块共享内存的ID。
char *shmaddr是共享内存的起始地址
int shmflag是本进程对该内存的操作模式。如果是SHM_RDONLY的话,就是只读模式。其它的是读写模式
成功时,这个函数返回共享内存的起始地址。失败时返回-1。
shmdt()与shmat()相反,是用来禁止本进程访问一块共享内存的函数。
参数char *shmaddr是那块共享内存的起始地址。
成功时返回0。失败时返回-1。
此外,还有一个用来控制共享内存的shmctl()函数如下:
#include
#include
#include
int     shmctl( int shmid , int cmd , struct shmid_ds *buf );
int shmid是共享内存的ID。
int cmd是控制命令,可取值如下:
        IPC_STAT        得到共享内存的状态
        IPC_SET         改变共享内存的状态
        IPC_RMID        删除共享内存
struct shmid_ds *buf是一个结构体指针。IPC_STAT的时候,取得的状态放在这个结构体中。如果要改变共享内存的状态,用这个结构体指定。
返回值:        成功:0
                失败:-1
刚才我们的mpaste.c程序中还可以加入这样几句。
struct shmid_ds buf;
... ...
shmctl( shmid , IPC_STAT , &buf );      //      取得共享内存的状态
... ...
shmctl( shmid , IPC_RMID , &buf );      //      删除共享内存
注意!!!!!!!!!:在使用共享内存,结束程序退出后。如果你没在程序中用shmctl()删除共享内存的话,一定要在命令行下用ipcrm命令删除这块共享内存。你要是不管的话,它就一直在那儿放着了。
简单解释一下ipcs命令和ipcrm命令。
取得ipc信息:
ipcs [-m|-q|-s]
-m      输出有关共享内存(shared memory)的信息
-q      输出有关信息队列(message queue)的信息
-s      输出有关“遮断器”(semaphore)的信息
%ipcs -m
删除ipc
ipcrm -m|-q|-s shm_id
%ipcrm -m 105
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/35795/showart_1090618.html
  发表评论 查看评论(共有条评论)
 
 


最新资讯更多>> 
· OpenMoko面临MP3专利困局
· Windows 7生不逢时 Linux能否成..
· Mozilla主席贝克专访:不惧Chr..
· Sun麦克尼利暗讽IBM微软 倡导I..
· 微软牵手Novell两周年:争议和抵..
· 微软、Novell合作两周年庆 再推..
· 红帽虚拟化全面中标新联通IDC建..
· 袁萌:开源软件需告别误区
· 综述:Solaris能否成为Sun的救星
· Linux平台刻录工具NeroLINUX 3..
论坛热点更多>> 
· 为什么业界对firefox一片叫好?
· 各地车展 合集
· 蚊子MM生活照-真实
· 大连车展
· 各式各样的清纯
· 精选车模
· 各地车展 合集二
· 你是否已经审美疲劳了?(网..
· 您最希望沙龙活动的所在地:..
· 自己修改的ADC0809驱动,God..
文档更新更多>> 
· 提供SPI/SDIO接口的小尺寸wi-fi模..
· ubuntu pdf乱码、方块字
· 解析linux根文件系统的挂载过程
· linux开机启动脚本的顺序
· phpMyAdmin 3.1.0 Beta 1 - MySQ..
· Linux 内核的WorkQueues API做了..
· 纠正了aMule中的文件名乱码
· rhel5系统的安装
· 算法合集一、数论算法 1.求两数..
· 【转自外文】用SD卡模拟CDROM光盘..
 
关于我们 | 联系方式 | 广告合作 | 诚聘英才 | 网站地图 | 友情链接 | 免费注册

Copyright © 2001-2008 ChinaUnix.net All Rights Reserved

感谢所有关心和支持过ChinaUnix的朋友们

京ICP证041476号