利用共享内存实现进程间通信--简单剪贴板实例
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
head = pos = shmat( shmid , 0 , 0 ); //
允许本进程使用这块共
out_ptr = out_data ;
//
从共享内存中取得数据
while( *pos != '\0' )
{
*out_ptr = *pos ;
out_ptr++ ;
pos++ ;
}
来自百度文库*out_ptr = '\0' ;
shmkey = ftok( "mcut" , 'a' );
//
计算标识符
//
shmid 开辟共享内存
shmid = shmget( shmkey , sizeof(in_data) , IPC_CREAT | 0666 ) ;
head = pos = shmat( shmid , 0 , 0 ); // 享内存
shmdt()与 shmat()相反,是用来禁止本进程访问一块共享内存的函数。 参数 char *shmaddr 是那块共享内存的起始地址。 成功时返回 0。失败时返回-1。
此外,还有一个用来控制共享内存的 shmctl()函数如下: #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h>
允许本进程使用这块共
in_ptr = in_data ;
//
开始从标准输入输入数据,暂时存在 in_data 里。
while( (in_tmp=getchar()) != EOF )
{
*in_ptr = in_tmp ;
in_ptr++ ;
}
*in_ptr = '\0' ; in_ptr = in_data ;
int flag 是这块内存的模式(mode)以及权限标识(关于权限的意思,请参阅本系列第五章)。
模式可取如下值:
新建:IPC_CREAT
使用已开辟的内存:IPC_ALLOC
如果标识符以存在,则返回错误值:IPC_EXCL
然后将“模式” 和“权限标识”进行“或”运算,做为第三个参数。
如: IPC_CREAT | IPC_EXCL | 0666
shmget()是用来开辟/指向一块共享内存的函数。参数定义如下:
key_t shmkey 是这块共享内存的标识符。如果是父子关系的进程间通信的话,这个标识符
用 IPC_PRIVATE 来代替。但是刚才我们的两个进程没有任何关系,所以就用 ftok()算出来
一个标识符使用了。
int shmsiz 是这块内存的大小.
这个函数成功时返回共享内存的 ID,失败时返回-1。
shmat()是用来允许本进程访问一块共享内存的函数。 int shmid 是那块共享内存的 ID。 char *shmaddr 是共享内存的起始地址 int shmflag 是本进程对该内存的操作模式。如果是 SHM_RDONLY 的话,就是只读模式。其 它的是读写模式 成功时,这个函数返回共享内存的起始地址。失败时返回-1。
中。如果要改变共享内存的状态,用这个结构体指定。
返回值:
成功:0
失败:-1
刚才我们的 mpaste.c 程序中还可以加入这样几句。
struct shmid_ds buf;
... ...
shmctl( shmid , IPC_STAT , &buf );
//
取得共享内存的状态
... ...
shmctl( shmid , IPC_RMID , &buf );
//
开始写入共享内存
while( *in_ptr != '\0' )
{
*pos = *in_ptr ;
pos++;
in_ptr++;
}
*pos = '\0' ;
shmdt( head );
//
禁止本进程使用这块内存
return 0;
}
#include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdio.h>
printf( "%s\n" , out_data );
fflush( stdout );
shmdt( head );
//
禁止本进程使用这块共享内存
return 0;
}
如何?明白多少了?
要使用共享内存,应该有如下步骤:
1.开辟一块共享内存
shmget()
2.允许本进程使用共某块共享内存 shmat()
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 );
3.写入/读出
4.禁止本进程使用这块共享内存 shmdt()
5.删除这块共享内存
shmctl()或者命令行下 ipcrm
上面的程序中用到了如下函数,我们一一解释一下。
首先是 ftok()。它有两个参数,一个是字符串,一个是字符。字符串一般用当前进程的程 序名,字符一般用来标记这个标识符所标识的共享内存是这个进程所开辟的第几个共享内 存。ftok()会返回一个 key_t 型的值,也就是计算出来的标识符的值。
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 的时候,取得的状态放在这个结构体
#include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdio.h>
int
main()
{
key_t shmkey;
int
shmid , in_tmp ;
char *head , *pos ,
in_data[4096] , *in_ptr ;
其次,操作共享内存,我们用到了下面的函数 #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h>
int void int
shmget( key_t shmkey , int shmsiz , int flag ); *shmat( int shmid , char *shmaddr , int shmflag ); shmdt( char *shmaddr );
//
删除共享内存
注意!!!!!!!!!:在使用共享内存,结束程序退出后。如果你没在程序中用 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
利用共享内存实现进程间通信
在两个进程间共享数据的方法,至今为止我们只说过利用管道。管道只是利用了输入输出重 定向的原理,非常简单。而且只能在父子进程间使用。很多场合下这种方法是无法满足我们 的要求的。 那么现在,我们又有了一种新的方法——利用共享内存(shared memory)。这可以使我们在 任意两个进程间传递数据,而且也是相对简单容易实现的一个方法。 注意:在正常情况下,一个进程的所使用的内存区是不允许其它进程访问的。这里我们要开 辟的共享内存是例外。 我们来做一个简单的剪贴板。从标准输入向 mcut 输入数据,mcut 将其放在共享内存中,然 后 mpaste 从共享内存中读出数据并显示。