并发 ------- 2.4 历程间的通信 - 共享内存

打印 上一主题 下一主题

主题 532|帖子 532|积分 1596

前言:历程间的通信方式包罗


    IPC: 
        1、管道
            pipe 无名管道
            fifo 有名管道 
        2、信号 signal        
        3、消息队列 System V消息队列 / POSIX消息队列     
        4、共享内存 System V共享内存 / POSIX共享内存        <-----------
        5、信号量   System V信号量 / POSIX信号量 
        6、socket套接字

1、共享内存 


    共享内存是历程间通信的一种方式,多个历程共享一段内存空间 “共享内存” 
    由于多个历程共享同一个内存,你往这个内存中写入数据,现实上就是往我的内存中写入数据
随内核的持续性 
        实现方式: 
            在内核中开辟了一块空间,其他历程通过 “内存映射” 的方式 
            获取到这个共享内存的首地点 
            历程p1可以映射这段内存,其他历程p2也可以映射这段内存 
            p1往这段内存中写入数据,现实上就是往p2中写入数据  

2、System V 共享内存的相关接口函数 


        System V IPC (msg/shm/sem) 操作流程: 
            (1)获取键值key 
            (2)创建或打开一个IPC对象,获取IPC对象的id 
            (3)操作:发送/接收 
            (4)其他控制操作: 删除/获取、设置属性/...
 
    1)获取键值key - ftok函数

    2)创建大概打开一个System V共享内存 shmget 

            NAME
                shmget - allocates a System V shared memory segment
            SYNOPSIS
                #include <sys/ipc.h>
                #include <sys/shm.h>
                int shmget(key_t key, size_t size, int shmflg);
                    功能:获取一块共享内存 
                    参数: 
                        key: 共享内存的键值 
                        size: 共享内存的巨细 ,单位 字节 
                                当现实操作是 创建一个新的共享内存时,必须指定一个不为0的size值  
                                当现实操作是 打开一个共享内存时,那么size==0 
                        shmflg: 标志
                                (1)创建标志 
                                    IPC_CREAT | 权限 
                                    例子: 
                                        IPC_CREAT | 0666 
                                    注意: 
                                        如果创建失败的缘故原由 是因为已经存在了 
                                        且 创建的标志为 IPC_CREAT | IPC_EXCL 一起使用 
                                        此时 errno == EEXIST 
                                (2)打开标志 
                                     0  
                    返回值: 
                        成功,返回共享内存的id 
                        失败,返回-1,并设置errno 


    3)共享内存的映射和解映射 


        NAME
            shmat, shmdt - System V shared memory operations
        SYNOPSIS
            #include <sys/types.h>
            #include <sys/shm.h>
            void *shmat(int shmid, const void *shmaddr, int shmflg);
                功能:用来映射一个System V共享内存到历程的地点空间
                参数: 
                    shmid: 共享内存的id 
                    shmaddr:指定映射到历程地点空间的哪个位置上 
                                一般为 NULL 让它自行分配 
                    shmflg:映射标志 
                            SHM_RDONLY  只读 
                            0           可读可写
                返回值: 
                    成功,返回映射地区的首地点 
                    失败,返回(void *) -1,同时errno被设置


            int shmdt(const void *shmaddr);
                功能:解除映射
                参数:
                    shmaddr: 映射地区的首地点 
                返回值: 
                    成功,返回0 
                    失败,返回-1,并设置errno 

       
  1.             创建一个共享内存,实现父子进程的通信 
  2.                 子进程 --》 写入数据 
  3.                 父进程 --》 读取数据,并打印 
  4.                 #define PATHNAME "/home/china/"
  5.                 int main() 
  6.                 {
  7.                     //1.获取键值key 
  8.                     key_t key = ftok( PATHNAME, 5 );
  9.                     if( key == -1 )
  10.                     {
  11.                         perror("ftok error ");
  12.                         return -1;
  13.                     }
  14.                     printf("key = 0x%x\n", key );
  15.                     //2.创建或打开一个System V共享内存 
  16.                     int shm_id = shmget( key, 4096, IPC_CREAT | IPC_EXCL | 0666 );
  17.                     if( shm_id == -1 )
  18.                     {
  19.                         if( errno == EEXIST )   //已经存在 就直接打开
  20.                         {
  21.                             shm_id = shmget( key, 0, 0 );
  22.                         }
  23.                         else 
  24.                         {
  25.                             perror("shmget error ");
  26.                             return -1;
  27.                         }
  28.                     }
  29.                     printf("shm_id = %d\n", shm_id );
  30.                     //3.映射 
  31.                     char * p = shmat( shm_id, NULL, 0 );
  32.                     if( p == NULL )
  33.                     {
  34.                         perror("shmat error ");
  35.                         return -1;
  36.                     }
  37.                     //4.创建一个子进程 
  38.                     pid_t  pid = fork();
  39.                     if( pid > 0 )   //父进程 
  40.                     {
  41.                         //等待子进程退出 
  42.                         wait( NULL );
  43.                         //读取数据,打印
  44.                         printf("father : %s\n", p );
  45.                         //5.解除映射 
  46.                         shmdt( p );
  47.                     }
  48.                     else if( pid == 0 )   //子进程 
  49.                     {
  50.                         //写入数据
  51.                         printf("child : ");
  52.                         fgets( p, 128, stdin );
  53.                     }
  54.                     else 
  55.                     {
  56.                         perror("fork error ");
  57.                         shmdt( p );
  58.                         return -1;
  59.                     }
  60.                 }
复制代码

    4)共享内存的控制操作shmctl 


            NAME
                shmctl - System V shared memory control
            SYNOPSIS
                #include <sys/ipc.h>
                #include <sys/shm.h>
                int shmctl(int shmid, int cmd, struct shmid_ds *buf);
                    功能:对共享内存的其他控制操作
                    参数: 
                        shmid: 共享内存id 
                        cmd: 命令号  
                                IPC_RMID    删除  
                                IPC_STAT    获取属性 
                                IPC_SET     设置属性 
                                ...
                        buf: 结构体指针 , 具体根据cmd的差别,有差别寄义 
                                如果 cmd == IPC_RMID ,那么就填 NULL 
                    返回值: 
                        成功,返回0 
                        失败,返回-1,同时errno被设置

             
  1.           struct shmid_ds 
  2.                         {
  3.                             struct ipc_perm shm_perm;    /* Ownership and permissions */
  4.                             size_t          shm_segsz;   /* Size of segment (bytes) */
  5.                             time_t          shm_atime;   /* Last attach time */
  6.                             time_t          shm_dtime;   /* Last detach time */
  7.                             time_t          shm_ctime;   /* Last change time */
  8.                             pid_t           shm_cpid;    /* PID of creator */
  9.                             pid_t           shm_lpid;    /* PID of last shmat(2)/shmdt(2) */
  10.                             shmatt_t        shm_nattch;  /* No. of current attaches */
  11.                             ...
  12.                         };
复制代码

 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

半亩花草

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表