分享

如何用ftok来产生相关的key,然后共享内存

 antyoung 2011-09-02

出处: http://blog.csdn.net/hello_wyq/archive/2006/08/01/1006277.aspx

在IPC中,我们经常用用key_t的值来创建或者打开信号量,共享内存和消息队列。这个在IPC的环境中十分的重要,比如说,服务器创建了一个消息队列,等待客户机发送请求。那么如何创建或者打开已有的消息队列呢?一般而言,我们对于服务器使用的路径和项目id(proj_id)是已知的,所以客户机可以获取相同的key来打开 消息队列并进行操作。下面就是ftok的使用原型:
# include <sys/types.h>
# include <sys/ipc.h>

key_t ftok(const char *pathname, int proj_id);
注意:
1)pathname一定要在系统中存在
2)pathname一定是使用进程能够访问的
3)proj_id是一个1-255之间的一个整数值,典型的值是一个ASCII值。
当成功执行的时候,一个key_t值将会被返回,否则-1被返回。我们可以使用errno来确定具体的错误信息如果我们很懒惰的话,不妨就使用perror函数来答应对应的出错字符信息。
下面的程序简单的演示和打印如何使用ftok及其对应值
 
 
 
 

共享内存实现分为两个步骤:
一、创建共享内存,使用shmget函数。
二、映射共享内存,将这段创建的共享内存映射到具体的进程空间去,使用shmat函数

由于这种方式是直接对用户空间的内存进行映射,故效率较高,使用起来也方便;

但需要注意的是,多个进程并发访问共享内存时的同步控制问题,可用信号量操作解决。

系统调用:shmget( ) ;
原型:int shmget ( key_t key, int size, int shmflg );
    返回值:如果成功,返回共享内存段标识符。
    如果失败,则返回- 1:
    errno = EINVAL (无效的内存段大小)
           EEXIST (内存段已经存在,无法创建)
           EIDRM (内存段已经被删除)
           ENOENT (内存段不存在)
           EACCES (权限不够)
           ENOMEM (没有足够的内存来创建内存段)

函数中的key_t如何获得已经在上一篇文章中说明了

系统调用:shmat();
原型:int shmat ( int shmid, char *shmaddr, int shmflg);
    返回值:如果成功,则返回共享内存段连接到进程中的地址。
    如果失败,则返回- 1:
    errno = EINVAL (无效的IPC ID 值或者无效的地址)
           ENOMEM (没有足够的内存)
           EACCES (存取权限不够)

当一个进程不在需要共享的内存段时,它将会把内存段从其地址空间中脱离。
系统调用:shmdt();
调用原型:int shmdt ( char *shmaddr );
    返回值:如果失败,则返回- 1:
        errno = EINVAL (无效的连接地址)

举例:shm1.c

#include <stdio.h>

#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
int main()
{
   key_t ipckey;
   int shmid;
   int i;
   char *addr_c;
   char srcbuf[8]="abcdefg";
   ipckey=ftok("/home/yds/tmp/shmipc",0);
   shmid=shmget(ipckey,1024,IPC_CREAT|0666);
   if(shmid==-1)
    {
       printf("creat shm error!\n");
       return -1;
     }
   addr_c=(char *)shmat(shmid,0,0);
   if((int)addr_c==-1)
    {
       printf("attach shm error!\n");
       return -1;
     }
   while(1)
   {     
       for(i=0;i<strlen(srcbuf);i++)
       {
         srcbuf[i]=srcbuf[i]+1;
       }
       strcpy(addr_c,srcbuf);
       sleep(1);  
   }
   shmdt(addr_c);
   return 0;
}

shm2.c

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>

int main()
{
key_t ipckey;
int shmid;
int i;
char *addr_c;
ipckey=ftok("/home/yds/tmp/shmipc",0);
shmid=shmget(ipckey,1024,IPC_CREAT|0666);
if(shmid==-1)
{
printf("creat shm error!\n");
return -1;
}
addr_c=(char *)shmat(shmid,0,0);
if((int)addr_c==-1)
{
printf("attach shm error!\n");
return -1;
}

while(1)
{
sleep(2);
printf("string(shm) is:%s\n",addr_c);
}
shmdt(addr_c);
return 0;
}

以上两个程序shm1.c先运行,shm2.c后运行 由于没有采用信号量机制对进程进行同步,所以只能先人为规定一下执行顺序了,只在说明问题,不在实用。

进程shm1负责每秒钟向共享内存中写入数据, shm2负责每两秒从共享内存中读数据,这个例子中key_t ipckey 保证操作的共享内存是同一个。上一篇文章有关于key_t的解释


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多