设为首页 加入收藏

TOP

【进程间通信】常用方式汇总(一)
2023-07-23 13:37:59 】 浏览:53
Tags:程间通 常用方

【进程间通信】常用方式汇总

随着我们的进程越来越多,难免不同进程之间要互相传输一些数据,那么这个时候该怎么办呢?

下面主要简单了解一下,进程间通信(InterProcess Communication,IPC)的几种实现方式!

 

1、管道模型

管道模型与软件生命周期模型——瀑布模型(Waterfall Model)很相似。

所谓的瀑布模型,其实就是将整个软件开发过程分成多个阶段,往往是上一个阶段完全做完,才将输出结果交给下一个阶段。

image-20220922134815245

还记得咱们最初学 Linux 命令的时候,有下面这样一行命令:

ps -ef | grep 关键字 | awk '{print $2}' | xargs kill -9

这里面的竖线“|”就是一个管道。它会将前一个命令的输出,作为后一个命令的输入。

从管道的这个名称可以看出来,管道是一种单向传输数据的机制,它其实是一段缓存,里面的数据只能从一端写入,从另一端读出。如果想互相通信,我们需要创建两个管道才行。

管道又可以分为匿名管道和命名管道!

 

1.1 匿名管道

如上命令:

ps -ef | grep 关键字 | awk '{print $2}' | xargs kill -9

匿名管道:用"|” 表示的管道,意思就是这个类型的管道没有名字,用完了就销毁了。竖线代表的管道随着命令的执行自动创建、自动销毁。用户甚至都不知道自己在用管道这种技术,就已经解决了问题。

 

1.2 命名管道

命名管道,这个类型的管道需要通过 mkfifo 命令显式地创建。

mkfifo donge		#建立一个管道

donge就是这个管道的名称。管道以文件的形式存在,这也符合 Linux 里面一切皆文件的原则。

 

下面我们看一下文件类型

ls -l
prw-rw-r-- 1 dong dong     0 Sep 28 17:09 donge

可以看到,这个文件的类型是 p,就是 pipe 的意思。

 

往管道中写入数据

echo "hello world" > donge

这个时候,管道里面的内容没有被读出,这个命令就是停在这里的,即进程被堵塞。

这说明当一个项目组要把它的输出交接给另一个项目组做输入,当没有交接完毕的时候,前一个项目组是不能撒手不管的。

重新打开一个终端,读出管道数据

cat < hello 
hello world

一方面,我们能够看到,管道里面的内容被读取出来,打印到了终端上;

另一方面,echo 那个命令正常退出了,也即交接完毕,前一个项目组就完成了使命,可以解散了。

 

管道通信,我们可以看出,瀑布模型的开发流程效率比较低下,因为团队之间无法频繁地沟通。而且,管道的使用模式,也不适合进程间频繁的交换数据

 

2、消息队列

image-20220922135603302

消息队列可以理解为发邮件,每一封邮件都视为一个独立的数据单元,也就是消息体,每个消息体都是固定大小的存储块,在字节流上不连续

这个消息结构的定义我写在下面了。这里面的类型 type 和正文 text 没有强制规定,只要消息的发送方和接收方约定好即可。

struct msg_buffer {
    long mtype;
    char mtext[1024];
};

 

2.1 创建消息队列

消息队列的创建,需要用到msgget函数

int msgget(key_t key, int msgflg);
  • key:该参数是消息队列的唯一标识,由ftok生成。

  • msgflg:取值有以下几个选择:IPC_CREATIPC_EXCL ,这两个参数详细的作用可以man msgflg看详细介绍。

  • 返回值:返回一个近乎唯一的Message queue id

 

那么,key是如何由ftok生成的呢?

我们可以指定一个文件,调用ftok ,它会根据这个文件的 inode,生成一个近乎唯一的 key

key_t ftok(const char *pathname, int proj_id);
  • pathname:文件信息,必须指定在一个存在的,可访问的文件
  • proj_id8bit的数据,0-255随意设定

这样就可以获得一个近乎唯一的key了!

 

只要在这个消息队列的生命周期内,这个文件不要被删除就可以了。只要不删除,无论什么时刻,再调用 ftok,也会得到同样的 key。

 

综上,创建一个消息队列只需两步:

①:ftok生成一个key

②:msgget生成一个消息队列的ID

如下:

#include <stdio.h>
#include <stdlib.h>
#include <sys/msg.h>
 
 
int main() {
  int messagequeueid;
  key_t key;
 
 
  if((key = ftok("/root/messagequeue/messagequeuekey", 1)) < 0)
  {
      perror("ftok error");
      exit(1);
  }
 
 
  printf("Message Queue key: %d.\n", key);
 
 
  if ((messagequeueid = msgget(key, IPC_CREAT|0777)) == -1)
  {
      perror("msgget error");
      exit(1);
  }
 
 
  printf("Message queue id: %d.\n", messagequeueid);
}

ftok要指定一个存在的文件,所以我们在执行之前,需要创建该文件。

 

查看消息队列

System V IPC 体系有一个统一的命令行工具:ipcmkipcsipcrm 用于创建、查看和删除 IPC 对象。

查看创建的IPC对象:ipcs -q

dong@ubuntu:~//Interprocess_Communication$ ipcs 

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages    
0x01110005 0          dong       777        0            0           

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status      

------ Semaphore Arrays --------
key        semid      owner      perms      nsems

 

2.2 发送消息

消息队列发送消息,主要调用msgsnd 函数

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
  • msqid:该参数是msgget所得到的message queueid
  • msgp:消息结构体
struct msg_buffer {
    long mtype;
    char mtext[1024];
};
  • msgsz:表示消息结构体中,mtext最大长度
  • msgflg:一位掩码,可取值有:IPC_NOWAITMSG_COPYMSG_EXCEPTMSG_NOERROR,取值说明可见man msgsnd

 

2.3 接收消息

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇实现基于文件验证的vsftpd虚拟用户 下一篇管理配置Ansible

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目