半亩花草 发表于 2024-7-30 12:56:13

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

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


    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 
       
            创建一个共享内存,实现父子进程的通信 
                子进程 --》 写入数据 
                父进程 --》 读取数据,并打印 

                #define PATHNAME "/home/china/"

                int main() 
                {
                    //1.获取键值key 
                    key_t key = ftok( PATHNAME, 5 );
                    if( key == -1 )
                    {
                        perror("ftok error ");
                        return -1;
                    }
                    printf("key = 0x%x\n", key );

                    //2.创建或打开一个System V共享内存 
                    int shm_id = shmget( key, 4096, IPC_CREAT | IPC_EXCL | 0666 );
                    if( shm_id == -1 )
                    {
                        if( errno == EEXIST )   //已经存在 就直接打开
                        {
                            shm_id = shmget( key, 0, 0 );
                        }
                        else 
                        {
                            perror("shmget error ");
                            return -1;
                        }
                    }
                    printf("shm_id = %d\n", shm_id );

                    //3.映射 
                    char * p = shmat( shm_id, NULL, 0 );
                    if( p == NULL )
                    {
                        perror("shmat error ");
                        return -1;
                    }

                    //4.创建一个子进程 
                    pid_t  pid = fork();

                    if( pid > 0 )   //父进程 
                    {
                        //等待子进程退出 
                        wait( NULL );

                        //读取数据,打印
                        printf("father : %s\n", p );

                        //5.解除映射 
                        shmdt( p );
                    }
                    else if( pid == 0 )   //子进程 
                    {
                        //写入数据
                        printf("child : ");
                        fgets( p, 128, stdin );
                    }
                    else 
                    {
                        perror("fork error ");
                        shmdt( p );
                        return -1;
                    }
                }
    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被设置
             
          struct shmid_ds 
                        {
                            struct ipc_perm shm_perm;    /* Ownership and permissions */
                            size_t          shm_segsz;   /* Size of segment (bytes) */
                            time_t          shm_atime;   /* Last attach time */
                            time_t          shm_dtime;   /* Last detach time */
                            time_t          shm_ctime;   /* Last change time */
                            pid_t           shm_cpid;    /* PID of creator */
                            pid_t           shm_lpid;    /* PID of last shmat(2)/shmdt(2) */
                            shmatt_t        shm_nattch;  /* No. of current attaches */
                            ...
                        };
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 并发 ------- 2.4 历程间的通信 - 共享内存