macOS跨进程通信: FIFO(有名管道) 创建实例

2024-01-03 19:44

本文主要是介绍macOS跨进程通信: FIFO(有名管道) 创建实例,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一: 简介

在类linux系统中管道分为有名管道和匿名管道。两者都能单方向的跨进程通信。

  • 匿名管道(pipe): 必须是父子进程之间,而且子进程只能由父进程fork() 出来的,才能继承父进程的管道句柄,一般mac 开发用的很少。
  • 有名管道(fifo)又叫命名管道: 可以在同一台机器,没有关系的进程间通信。 其本质是本地创建一个文件,然后使用其路径作为纽带。 open后再内核空间产生管道,不同进程之间分别连接管道的读和写的端口进行通信。

这里主要针对有名管道进行研究。

二:主要函数

1. int mkfifo(const char *, mode_t);

第一个参数是路径,可以放在tmp路径下,比如const char *fifoName = "/tmp/com.jimbo.fifo";
mode_t代表赋予的权限,测试用0777就可以了。

2. int open(const char *, int, ...)

  • 返回值为,打开的管道的操作句柄,读写都需要它
  • 第一个参数是路径,同上
  • 第二个参数为打开模式:
#define O_RDONLY        0x0000          /* open for reading only */ 只读
#define O_WRONLY        0x0001          /* open for writing only */ 只写
#define O_NONBLOCK      0x00000004      /* no delay */				不阻塞
...

demo主要使用上面三种模式,

  • 发送端使用O_WRONLY
  • 接收端使用O_WRONLY
  • O_NONBLOCK代表open文件的时候,这个方法是否需要阻塞,默认不传是阻塞的.

3. ssize_t read(int, void *, size_t)

往管道读取数据。常规操作,传入open后的返回句柄,和字符串地址和最大长度

4. ssize_t write(int __fd, const void * __buf, size_t __nbyte)

往管道写入数据。常规操作,传入open后的返回句柄,和字符串地址和字符串长度

三:demo代码

如下图,创建了两个app,分别为发送端(写数据)和接收端(读数据)
在这里插入图片描述

1. 发送端主要逻辑

  • 主要创建了mkfifo一个管道

  • 创建了子进程

  • open() 阻塞式的等子进程打开管道文件

  • 上一步阻塞过了后,点击writeMsg往管道中写入消息。

主要代码: ViewController.mm 文件代码

//发送端
#import "ViewController.h"
#include <sys/unistd.h>
#include <sys/stat.h>static const char *fifoName = "/tmp/com.jimbo.fifo";@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];[self.view.window setTitle:@"Main window"];int ret = 0;if (access(fifoName, F_OK) == -1) {//管道不存在,创建一个新的ret = mkfifo(fifoName, 0777);if (ret != 0) {NSLog(@"mkfifo failed! ret:%i", ret);return;}}//启动子进程NSString *subAppp = [[NSBundle mainBundle] pathForResource:@"PipeApp_Sub" ofType:@"app"];subAppp = [NSString stringWithFormat:@"%@/Contents/MacOS/PipeApp_Sub", subAppp];NSTask *task = [[NSTask alloc] init];[task setLaunchPath:subAppp];NSError *error;[task launchAndReturnError:&error];//阻塞监听子进程打开 读端。self.writePipeID =  open(fifoName,O_WRONLY);printf("open fd:%i\n", self.writePipeID);if(self.writePipeID<0){perror("writer open err");return ;}
}- (IBAction)writeMsg:(id)sender {//往管道发送消息,消息为ui的文本框的数据const char *text = [self.textLabel.stringValue UTF8String];ssize_t writeSize =  write(self.writePipeID, text, strlen(text)+1);NSLog(@"write succed size:%zi", writeSize);
}

2. 接收端主要逻辑

  • 收到非阻塞的O_NONBLOCK 打开只读管道,(打开后发送端的阻塞会通过)

  • 等到发送端发送了数据后。。。

  • 点击接收数据的按钮receiveMsg, read()函数读取管道中的数据,并显示在ui的textView

//接收端
#import "ViewController.h"
#include <sys/stat.h>@interface ViewController()
@property (nonatomic, assign) int pipeReadID;
@property (unsafe_unretained) IBOutlet NSTextView *textView;@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];const char *fifoName = "/tmp/com.jimbo.fifo";// 由于是ui 主线程,所以选择了 非阻塞式的打开 管道self.pipeReadID = open(fifoName, O_RDONLY | O_NONBLOCK);if (self.pipeReadID < 0) {NSLog(@"open 失败了");self.textView.string = @"open 失败了";} else {self.textView.string = @"点击接收按钮,接收数据";}
}- (IBAction)receiveMsg:(id)sender {size_t n;char line[PIPE_BUF+1];n = read(self.pipeReadID, line, PIPE_BUF);NSLog(@"count:%zu get msg: %s", n ,line);if (n > PIPE_BUF || n < 0) {return;}self.textView.string = [NSString stringWithFormat:@"收到的数据:%@", [[NSString alloc] initWithBytes:line length:n encoding:NSUTF8StringEncoding]];
}- (void)dealloc {close(self.pipeReadID);
}@end

这篇关于macOS跨进程通信: FIFO(有名管道) 创建实例的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/566837

相关文章

java图像识别工具类(ImageRecognitionUtils)使用实例详解

《java图像识别工具类(ImageRecognitionUtils)使用实例详解》:本文主要介绍如何在Java中使用OpenCV进行图像识别,包括图像加载、预处理、分类、人脸检测和特征提取等步骤... 目录前言1. 图像识别的背景与作用2. 设计目标3. 项目依赖4. 设计与实现 ImageRecogni

Window Server创建2台服务器的故障转移群集的图文教程

《WindowServer创建2台服务器的故障转移群集的图文教程》本文主要介绍了在WindowsServer系统上创建一个包含两台成员服务器的故障转移群集,文中通过图文示例介绍的非常详细,对大家的... 目录一、 准备条件二、在ServerB安装故障转移群集三、在ServerC安装故障转移群集,操作与Ser

Window Server2016 AD域的创建的方法步骤

《WindowServer2016AD域的创建的方法步骤》本文主要介绍了WindowServer2016AD域的创建的方法步骤,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录一、准备条件二、在ServerA服务器中常见AD域管理器:三、创建AD域,域地址为“test.ly”

mac中资源库在哪? macOS资源库文件夹详解

《mac中资源库在哪?macOS资源库文件夹详解》经常使用Mac电脑的用户会发现,找不到Mac电脑的资源库,我们怎么打开资源库并使用呢?下面我们就来看看macOS资源库文件夹详解... 在 MACOS 系统中,「资源库」文件夹是用来存放操作系统和 App 设置的核心位置。虽然平时我们很少直接跟它打交道,但了

Java操作ElasticSearch的实例详解

《Java操作ElasticSearch的实例详解》Elasticsearch是一个分布式的搜索和分析引擎,广泛用于全文搜索、日志分析等场景,本文将介绍如何在Java应用中使用Elastics... 目录简介环境准备1. 安装 Elasticsearch2. 添加依赖连接 Elasticsearch1. 创

使用C#代码计算数学表达式实例

《使用C#代码计算数学表达式实例》这段文字主要讲述了如何使用C#语言来计算数学表达式,该程序通过使用Dictionary保存变量,定义了运算符优先级,并实现了EvaluateExpression方法来... 目录C#代码计算数学表达式该方法很长,因此我将分段描述下面的代码片段显示了下一步以下代码显示该方法如

macOS怎么轻松更换App图标? Mac电脑图标更换指南

《macOS怎么轻松更换App图标?Mac电脑图标更换指南》想要给你的Mac电脑按照自己的喜好来更换App图标?其实非常简单,只需要两步就能搞定,下面我来详细讲解一下... 虽然 MACOS 的个性化定制选项已经「缩水」,不如早期版本那么丰富,www.chinasem.cn但我们仍然可以按照自己的喜好来更换

Python在固定文件夹批量创建固定后缀的文件(方法详解)

《Python在固定文件夹批量创建固定后缀的文件(方法详解)》文章讲述了如何使用Python批量创建后缀为.md的文件夹,生成100个,代码中需要修改的路径、前缀和后缀名,并提供了注意事项和代码示例,... 目录1. python需求的任务2. Python代码的实现3. 代码修改的位置4. 运行结果5.

使用IntelliJ IDEA创建简单的Java Web项目完整步骤

《使用IntelliJIDEA创建简单的JavaWeb项目完整步骤》:本文主要介绍如何使用IntelliJIDEA创建一个简单的JavaWeb项目,实现登录、注册和查看用户列表功能,使用Se... 目录前置准备项目功能实现步骤1. 创建项目2. 配置 Tomcat3. 项目文件结构4. 创建数据库和表5.

python多进程实现数据共享的示例代码

《python多进程实现数据共享的示例代码》本文介绍了Python中多进程实现数据共享的方法,包括使用multiprocessing模块和manager模块这两种方法,具有一定的参考价值,感兴趣的可以... 目录背景进程、进程创建进程间通信 进程间共享数据共享list实践背景 安卓ui自动化框架,使用的是