【Linux】共享内存--实现进程间通信

1. 概念

       共享内存使得多个进程可以访问同一块内存空间,无需进行若干次的内存拷贝,是最快的可用 IPC 形式。它本身无同步互斥机制,它的同步与互斥需要由进程自己完成,通过与信号量结合使用,来达到进程间的同步及互斥。

2. 操作

共享内存同信号量和消息队列有异曲同工之妙,前面我们已经了解了一些知识,此处相通的将不再赘述。

共享内存的操作:

#define SHMAT       //挂接:把上面打开的内存区域连接到用户的进程空间中  
#define SHMDT       //分离:将共享内存从当前进程中分离  
#define SHMGET      //创建:打开一个内存区域  
#define SHMCTL      //内存区域的控制:包括初始化和删除内存区域。 


函数:

#include <sys/types.h>  
#include <sys/shm.h>  
  
int shmget(key_t key, size_t size, int shmflg);           //创建共享内存  
void *shmat(int shmid, const void *shmaddr, int shmflg);  //映射到自己的内存空间  
int shmdt(const void *shmaddr);                           //解除映射  
int shmctl(int shmid, int cmd, struct shmid_ds *buf);     //控制共享内存  


参数解释:

sheget:创建或者打开一个共享内存,成功就返回相应的共享内存标识符,失败返回-1。

shmat:空间映射(挂接)。通过创建的共享内存,在它能被进程访问之前,需要把该段内存映射到用户进程空间。shmaddr 是用来指定共享内存映射到当前进程中的地址位置,要想该设置有用,shmflg 必须设置为 SHM_RND 标志。大部分情况下,应该设置为为空指针 (void *)0。让系统自动选择地址,从而减小程序对硬件的依赖性。shmflg 除了上面的设置以外,还可以设置为 SHM_RDONLY,使得映射过来的地址只读。如果函数调用成功,返回映射的地址的第一个字节,否则返回-1。

shmdt:解除映射(分离)

shmctl:控制共享内存,明确的三个参数。struct shmid_ds 定义在 include/linux/shm.h,如下。cmd 有 IPC_STAT,IPC_SET,IPC_RMID,含义和消息队列一样。

           

struct shmid_ds {  
    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;  
    };  
    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 */  
};


3. 命令

查看共享内存:ipcs -m

删除共享内存:ipcrm -m shmid


4. 举例来实现进程间通信。


Makefile  的编写:


comm.h 的代码:


comm.c 的代码:




server.c 的代码:


client.c 的代码:



运行结果如下:


当只是运行了 server 并未运行 client 时,屏幕上不输出任何东西,我们可以看到刚开始的几行是空白的;

当在运行 server 的基础上继续在另一个终端运行 client 后,会发现开始输出 A,而只要不终止 client 的运行,就会一直挂接,连续打印,输出呈递增规律。


当我们终止了 client  的运行后,会发现此时输出在屏幕上的 A 不再增加,而是维持最后一次的输出结果继续打印。

以上的结果就很明显地告诉我们已经实现了进程间通信。

我们可以通过命令查看一下挂接数,同样印证了我们共享内存进程间通信的观点。


当查看挂接数的时候,需要在 root 用户下进行操作,否则将看不到想要的结果,我们切换到  root  用户下运行,然后查看。



打开第三个终端查看或者在 Xshell 下查看均可。





分析:当我们只是输入命令而不运行的话会发现并不存在任何东西,且屏幕上未输出结果;

            当我们先运行 server  后出现了共享内存,此时挂接数为 1,屏幕上还是不输出结果;

            当我们再运行 client,此时挂接数为 2,屏幕上开始输出打印 A,可以论证此时已经通过共享内存实现了进程间通信;

            当我们关闭其中的任一个使其停止,挂接数就变为 1,全部关闭挂接数为 0,但是共享内存依然存在,可以说明共享内存的生命周期是随内核的。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值