6、操作系统——进程间通信(4)(system V-IPC:共享内存)

目录

一、原理(共享内存效率最高)

二、思想

三、使用共享内存的一般步骤

四、共享内存(SHM)的API

1、 shmget(获取共享内存的ID)

2、shmat(映射贡献内存)、shmdt(解除映射)

3、shmctl(获取或者设置共享内存的相关属性) 

五、写入数据(write代码)

六、读出数据(read代码)


一、原理(共享内存效率最高)

        操作内存通过一个内存将两个进程作为共享的区域,则两个进程可以直接访问一块内存,效率提高。

        共享内存一般要配合信号量、互斥锁等协调机制,让各个进程再高效交换数据的同时,不会发生数据践踏、破坏等意外。 

 二、思想

        进程与进程之间虚拟内存空间原本是相互独立、不能互相访问

        共享内存是通过某些方式,使得同一块物理内存多次映射到不同的进程虚拟空间之中

 

三、使用共享内存的一般步骤

1、获取共享内存对象的ID

2、将共享内存映射至本进程虚拟内存空间的某个区域

3、当不再使用时,解除映射关系

4、当没有进程再需要这块共享内存时,删除它

四、共享内存(SHM)的API

1、 shmget(获取共享内存的ID)

2、shmat(映射贡献内存)、shmdt(解除映射)

3、shmctl(获取或者设置共享内存的相关属性) 

  • IPC_RMID当所有都解除映射之后,才删除
  • SHM_LOCK不是锁定读写权限,而是锁定SHM能否与swap分区发生交换。若被设置了,则任何访问这个SHM的进程都将会遇到页错误。
  • 进程可以通过IPC_STAT后得到的mode来检测SHM_LOCKED信息
  • swap分区:硬盘空间不是内存空间
  • swap分区在系统的物理内存不够时,把硬盘内内存中的一部分空间释放处理啊,以供当前运行的程序使用,释放的空间可能来自一些很长事件没有什么操作的程序,这些被释放的空间被临时保存到swap分区中,等程序运行时,再从swap分区中回复保存的数据到内存中

五、写入数据(write代码)

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>

int main(int argc, char const *argv[])
{
    // 获得key值
    int key = ftok("./" , 'K');

    // 通过key值获得ID 
    int id = shmget( key , 4096 , IPC_CREAT | 0666 );

    // 映射共享内存
    char * shm_map = shmat(id , NULL , SHM_RND );//映射内存
    if ( shm_map == (char *)-1  )
    {
        perror("shmat error");
        return -1 ;
    }
    
    // 为所欲为
    memcpy(shm_map , "Hello GZ2123", sizeof("Hello GZ2123"));

    printf("拷贝成功!!!");

    return 0;
}

六、读出数据(read代码)

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>

int main(int argc, char const *argv[])
{
    // 获得key值
    int key = ftok("./" , 'K');

    // 通过key值获得ID 
    int id = shmget( key , 4096 , IPC_CREAT | 0666 );
    // 映射共享内存
    char * shm_map = shmat(id , NULL , SHM_RND );
    if ( shm_map == (char *)-1  )
    {
        perror("shmat error");
        return -1 ;
    }
    
    printf("共享内存的内容:%s\n" , shm_map );
    
    return 0;
}

七、共享内存+信号捕获

(1)写入

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>

int main(int argc, char const *argv[])
{
    // 获得key值
    int key = ftok("./" , 'K');

    // 通过key值获得ID 
    int id = shmget( key , 4096 , IPC_CREAT | 0666 );

    // 映射共享内存
    char * shm_map = shmat(id , NULL , SHM_RND );
    if ( shm_map == (char *)-1  )
    {
        perror("shmat error");
        return -1 ;
    }
    

    // 为所欲为
    int pid = *(int*)shm_map ;
    printf("对方pid :%d \n" , pid );

    while(1)
    {
        fgets(shm_map , 128 , stdin);
        // memcpy(shm_map , "Hello GZ2123", sizeof("Hello GZ2123"));
        printf("拷贝成功!!!\n");
        kill( pid , 3 );
        if( strstr(shm_map , "bye-bye"))
        {
            break ;
        } 
    }

    // 解除映射
    shmdt(shm_map);

    // 标记删除
    shmctl( id , IPC_RMID , NULL );
    
    return 0;
}

(2)读取

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>

int id;
char * shm_map ;

void read_msg( int sig )
{
    printf("共享内存的内容:%s\n" , shm_map );
        
    if( strstr(shm_map , "bye-bye"))
    {
        // 解除映射
        shmdt(shm_map);

        // 标记删除
        shmctl( id , IPC_RMID , NULL );
        exit( 1 );
    } 

    return  ;
}

int main(int argc, char const *argv[])
{
    signal( 3 , read_msg );
    // 获得key值
    int key = ftok("./" , 'K');

    // 通过key值获得ID 
    id = shmget( key , 4096 , IPC_CREAT | 0666 );

    // 映射共享内存
    shm_map = shmat(id , NULL , SHM_RND );
    if ( shm_map == (char *)-1  )
    {
        perror("shmat error");
        return -1 ;
    }
    

    // 为所欲为
    int pid = getpid();
    printf("我的ID:%d\n" ,pid );
    memcpy(shm_map , &pid , sizeof(int));

    // printf("拷贝成功!!!");
    while(1)
    {
        pause();
    } 
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45981798/article/details/129781062
今日推荐