Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1209451
  • 博文数量: 232
  • 博客积分: 7563
  • 博客等级: 少将
  • 技术积分: 1930
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-21 11:17
文章分类

全部博文(232)

文章存档

2011年(17)

2010年(90)

2009年(66)

2008年(59)

分类:

2008-05-30 09:44:08

  1. key_t ftok(const char *pathname, int proj_id);

    注意:
    1)pathname一定要在系统中存在
    2)pathname一定是使用进程能够访问的
    3)proj_id是一个1-255之间的一个整数值,典型的值是一个ASCII值。
    参考的是这个生成的key。

  2. int shmget(key_t key, size_t size, int shmflg);-- 建立共享内存
    参数介绍:
    key_t key
    -----------------------------------------------
        key标识共享内存的键值:是一个整数(实际上是int型的),当key为 0/IPC_PRIVATE
    。 当key的取值为IPC_PRIVATE,是一种特殊情况。每个进程都可以用键值0建立一个专供其私用的共享内存,函数shmget()将无条件创建一块新的共享内存;如果key的取值为0,而参数shmflg中设置了IPC_PRIVATE这个标志,则同样将创建一块新的共享内存。
        在IPC的通信模式下,不管是使用消息队列还是共享内存,甚至是信号量,每个IPC的对象(object)都有唯一的名字,称为“键”(key)。通过 “键”,进程能够识别所用的对象。“键”与IPC对象的关系就如同文件名称之于文件,通过文件名,进程能够读写文件内的数据,甚至多个进程能够共用一个文 件。而在IPC的通讯模式下,通过“键”的使用也使得一个IPC对象能为多个进程所共用。
        Linux系统中的所有表示System V中IPC对象的数据结构都包括一个ipc_perm结构,其中包含有IPC对象的键值,该键用于查找System V中IPC对象的引用标识符。如果不使用“键”,进程将无法存取IPC对象,因为IPC对象并不存在于进程本身使用的内存中。
        通常,都希望自己的程序能和其他的程序预先约定一个唯一的键值,但实际上并不是总可能的成行的,因为自己的程序无法为一块共享内存选择一个键值。因此,在 此把key设为IPC_PRIVATE,这样,操作系统将忽略键,建立一个新的共享内存,指定一个键值,然后返回这块共享内存IPC标识符ID。而将这个 新的共享内存的标识符ID告诉其他进程可以在建立共享内存后通过派生子进程,或写入文件或管道来实现。


    注意:键值和标识号是两码事。用文件系统打比方,则键值类似于文件名,而标识号类似于打开文件号。


    int size(单位字节Byte)
    -----------------------------------------------
        size是要建立共享内存的长度。所有的内存分配操作都是以页为单位的。所以如果一段进程只申请一块只有一个字节的内存,内存也会分配整整一页(在 i386机器中一页的缺省大小PACE_SIZE=4096字节)这样,新创建的共享内存的大小实际上是从size这个参数调整而来的页面大小。即如果 size为1至4096,则实际申请到的共享内存大小为4K(一页);4097到8192,则实际申请到的共享内存大小为8K(两页),依此类推。
    int shmflg
    -----------------------------------------------
        shmflg主要和一些标志有关。其中有效的包括IPC_CREAT和IPC_EXCL,它们的功能与open()的O_CREAT和O_EXCL相当。
        IPC_CREAT   如果共享内存不存在,则创建一个共享内存,否则打开操作。
        IPC_EXCL    只有在共享内存不存在的时候,新的共享内存才建立,否则就产生错误。

        如果单独使用IPC_CREAT,shmget()函数要么返回一个已经存在的共享内存的操作符,要么返回一个新建的共享内存的标识符。如果将 IPC_CREAT和IPC_EXCL标志一起使用,shmget()将返回一个新建的共享内存的标识符;如果该共享内存已存在,或者返回-1。 IPC_EXEL标志本身并没有太大的意义,但是和IPC_CREAT标志一起使用可以用来保证所得的对象是新建的,而不是打开已有的对象。对于用户的读 取和写入许可指定SHM_RSHM_W,(SHM_R>3)和(SHM_W>3)是一组读取和写入许可,而(SHM_R>6)和(SHM_W>6)是全局读取和写入许可。
    (``模式标志:9个bit的标志,和系统的文件权限使用相同的标志,不过执行标志无效。这些标志定义在中。)
    返回值
    -----------------------------------------------
    成功返回共享内存的标识符;不成功返回-1,errno储存错误原因。
        EINVAL        参数size小于SHMMIN或大于SHMMAX。
        EEXIST        预建立key所致的共享内存,但已经存在。
        EIDRM         参数key所致的共享内存已经删除。
        ENOSPC        超过了系统允许建立的共享内存的最大值(SHMALL )。
        ENOENT        参数key所指的共享内存不存在,参数shmflg也未设IPC_CREAT位。
        EACCES        没有权限。
        ENOMEM        核心内存不足。


  3. struct shmid_ds
    -----------------------------------------------
        shmid_ds数据结构表示每个新建的共享内存。当shmget()创建了一块新的共享内存后,返回一个可以用于引用该共享内存的shmid_ds数据结构的标识符。

    include/linux/shm.h

        struct shmid_ds {
            struct ipc_perm    shm_perm;      /* operation perms */
            int                shm_segsz;     /* size of segment (bytes) */
            __kernel_time_t    shm_atime;     /* last attach time */
            __kernel_time_t    shm_dtime;     /* last detach time */
            __kernel_time_t    shm_ctime;     /* last change time */
            __kernel_ipc_pid_t shm_cpid;      /* pid of creator */
            __kernel_ipc_pid_t shm_lpid;      /* pid of last operator */
            unsigned short     shm_nattch;    /* no. of current attaches */
            unsigned short     shm_unused;    /* compatibility */
            void               *shm_unused2; /* ditto - used by DIPC */
            void               *shm_unused3; /* unused */
        };
    struct ipc_perm
    -----------------------------------------------
        对于每个IPC对象,系统共用一个struct ipc_perm的数据结构来存放权限信息,以确定一个ipc操作是否可以访问该IPC对象。

        struct ipc_perm {
            __kernel_key_t   key;
            __kernel_uid_t   uid;
            __kernel_gid_t   gid;
            __kernel_uid_t   cuid;
            __kernel_gid_t   cgid;
            __kernel_mode_t mode;
            unsigned short   seq;
    };


    示例:

    要运行程序,需要在当前目录下建立一个share文件,share是一个空文件,没有任何意义,只是函数ftok需要一个文件名作参数,ftok另一个参数可以为任何数字。

    程序运行后,分为父子进程,子进程申请共享内存,然后等待父进程继续执行,父进程首先等待子进程申请到共享内存标识,然后输出共享内存中的内容,为了演示共享内存可以随时更新,程序中在子进程里产生随机数写入共享内存供父进程读取。
    代码如下:

    #include
    #include
    #include
    #include

    #include
    #include
    #include
    #include
    #include

    int shmID;
    char * buf;

    void finalize(int signo)
    {
    shmctl(shmID,IPC_RMID,NULL);

    exit(0);
    }

    int main()
    {
    int i = 1;  
    key_t shmKey;

    signal(SIGINT,finalize);
    signal(SIGTERM,finalize);

    if(fork() == 0) //子进程
    {  
       shmKey = ftok("share",16);   //可以使用任何大于0的数字,如果名字和数相同,则产生的key相同。
       if(shmKey == -1)
       {
        printf("创建key出错\n");
        exit(-1);
       }
      
       shmID = shmget(shmKey,20,IPC_CREAT | IPC_EXCL | 0666);
       if(shmID == -1)
       {
        printf("创建共享标识出错\n");
        exit(-1);
       }
      
       sleep(2); //等待父进程执行,好显示第一行为空。
       while(1)
       {
        buf = (char *)shmat(shmID,NULL,0);
        srandom(time(NULL));
        sprintf(buf,"%d",random());
        shmdt(buf);  
       }
    }
    else   //父进程
    {
       sleep(1); //让子进程先执行,以建立内存映射。
      
       shmKey = ftok("share",16);   //可以使用任何大于0的数字,如果名字和数相同,则产生的key相同。
       if(shmKey == -1)
       {
        printf("创建key出错\n");
        exit(-1);
       }
      
       shmID = shmget(shmKey,20,0); //0表示如果shmKey映射的不存在则报错。
       if(shmID == -1)
       {
        printf("引用共享标识出错\n");
        exit(-1);
       }
      
       while(1)
       {
        buf = (char *)shmat(shmID,NULL,0);
        printf("%d. 现在共享内存中的内容为:%s\n",i++,buf);
        shmdt(buf);
        sleep(1);
       }
    }

    return 0;
    }
参考文献:http://www.ibm.com/developerworks/cn/aix/library/au-ipc/index.html
阅读(1979) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2009-04-21 00:37:56

感谢啊!