Linux C 进程间的通信——共享内存、消息队列、信号量

        大家好,我是练习时长两年半的练习生,喜欢唱、跳、rap、敲代码,键来!

        在前面我们已经讲过,早期的进程间通信有三种——无名管道、有名管道、信号,(传送门:Linux C 进程间的通信——无名管道、有名管道、信号),今天就来浅谈一下在system V IPC的三种对象,也是进程通信的另外三种姿势——共享内存、消息队列、信号量。

目录

一、共享内存

        (一)概念

        (二)基操

        (三)相关API   

        (四)示例代码

二、消息队列

        (一)消息队列通信原理

        (二)基操

        (三)相关API

        (四)示例代码

三、信号量

(一)概念

(二)基操

(三)相关API

(四)代码实例

四、总结

补充:shell查看和删除IPC对象


一、共享内存

        (一)概念

        共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝。为了在多个进程间交换信息,内核专门留出了一块内存区,可以由需要访问的进程将其映射到自己的私有地址空间,进程就可以直接读写这一内存区而不需要进行数据的拷贝,从而大大提高进程通信的效率。

        (二)基操

                1》创建或者获取共享内存
                2》将共享内存映射到用户空间 

                3》解除映射
                4》删除共享内存 

        (三)相关API   

        1. 创建密钥 ftok

             注意!!!
        只要pathname和proj_id不变,就可以获得相同的key,如下,进程A和进程B获得的key相同。
        例子:
               进程A:key_t key1=ftok("xx.txt",0xa);
               进程B:key_t key2=ftok("xx.txt",0xa);

#include <sys/types.h>
#include <sys/ipc.h>

/**
  ***********************************
  *@brief  创建密钥key
  *@param  pathname:带路径的文件名
           proj_id:数字
       
  *@retval key_t
			成功返回key
			失败返回-1,并返回错误码EOF
  ***********************************
  */
key_t ftok(const char *pathname, int proj_id);

        2. 创建共享内存 shmget

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

/**
  ***********************************
  *@brief  创建或者获取共享内存
  *@param  key:密钥 
                IPC_PRIVATE:系统自动分配key
           size:共享内存的大小
           shmflg:权限,一般写为 IPC_CREAT|0666
  *@retval int 
			成功返回共享内存的id
			失败返回-1,并返回错误码EOF
  ***********************************
  */
int shmget(key_t key, size_t size, int shmflg);

        3. 共享内存映射到用户空间 shmat

#include <sys/types.h>
#include <sys/shm.h>

/**
  ***********************************
  *@brief  将共享内存映射到用户空间
  *@param  shmid:共享内存的id 
           shmaddr:需要映射到什么地方(地址)
           shmflg:访问权限
                    SH_RDONLY:只读
                    0:默认,可读可写
  *@retval int 
			成功返回映射后的地址
			失败返回-1,并返回错误码EOF
  ***********************************
  */
void *shmat(int shmid, const void *shmaddr, int shmflg);
				

          4. 解除映射 shmdt

#include <sys/types.h>
#include <sys/shm.h>

/**
  ***********************************
  *@brief  解除映射
  *@param  shmaddr:需要解除映射的地址
           
  *@retval int 
			成功返回0
			失败返回-1,并返回错误码EOF
  ***********************************
  */
int shmdt(const void *shmaddr);

        5. 管理共享内存 shmctl

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

/**
  ***********************************
  *@brief  删除
  *@param  shmid:需要解除映射的地址
           cmd:IPC_STAT  (获取对象属性)
				IPC_SET   (设置对象属性)
				IPC_RMID  (删除对象)
           buf:如果cmd为IPC_RMID,则此处置NULL
           
  *@retval int 
			成功返回0
			失败返回-1,并返回错误码EOF
  ***********************************
  */
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

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 */
		...
};

       

        (四)示例代码

        shm_write.c 和 shm_read.c代码基本一样,代表两个不同的进程,一个写入一个读取。shm_write.c中每次输入一行数据就会覆盖原来在共享内存空间的数据,输入quit退出输入状态,然后解除映射删除空间。shm_read.c读取到quit后也会退出,然后解除映射。

shm_write.c:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys
  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值