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

news2024/11/15 7:50:14

一: 简介

在类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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1354153.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于多反应堆的高并发服务器【C/C++/Reactor】(中)子线程 WorkerThread的实现 和 线程池ThreadPool的初始化

一、子线程 WorkerThread的实现 &#xff08;1&#xff09;工作线程 线程ID&#xff1a;每个线程都有一个唯一的ID,用于标识线程的名字&#xff1a;非必需&#xff0c;主要用于识别线程互斥锁&#xff1a;线程同步条件变量&#xff1a;线程阻塞EventLoop&#xff1a;在每个子…

WEB:探索开源PDF.js技术应用

1、简述 PDF.js 是一个由 Mozilla 开发的开源 JavaScript 库&#xff0c;用于在浏览器中渲染 PDF 文档。它的目标是提供一个纯粹的前端解决方案&#xff0c;摆脱了依赖插件或外部程序的束缚&#xff0c;使得在任何支持 JavaScript 的浏览器中都可以轻松地显示 PDF 文档。 2、…

解析大语言模型LLM的幻觉问题:消除错觉、提高认知

文章目录 前言一、幻觉介绍二、幻觉产生的原因三、幻觉的现象四、幻觉的分类五、幻觉解决方案六、幻觉待解决问题后记 前言 在人类的感知和认知过程中&#xff0c;幻觉一直是一个被广泛讨论和研究的问题。幻觉指的是一种虚假的感知或认知经验&#xff0c;使我们看到、听到或感…

YOLOv5算法进阶改进(12)— 引入YOLOv8中的C2f模块 | 提升小目标检测精度

前言:Hello大家好,我是小哥谈。YOLOv8是由Ultralytics开发的一个前沿的SOTA模型。它在以前成功的YOLO版本基础上,引入了新的功能和改进,进一步提升了其性能和灵活性。C2f模块和C3模块分别是YOLOv8和YOLOv5中的两种不同的模块设计,它们在结构和功能上有一些区别。本文将YOL…

很实用的ChatGPT网站—在线编程模块增补篇

很实用的ChatGPT网站&#xff08;http://chat-zh.com/&#xff09;——增补篇 今天介绍一个好兄弟开发的ChatGPT网站&#xff0c;网址[http://chat-zh.com/]。这个网站功能模块很多&#xff0c;包含生活、学习、医疗、法律、经济等很多方面。今天跟大家分享一下&#xff0c;新…

Java IO流介绍以及缓冲为何能提升性能

概念&#xff1a; 流是一种抽象概念&#xff0c;它代表了数据的无结构化传递。按照流的方式进行输入输出&#xff0c;数据被当成无结构的字节序或字符序列。从流中取得数据的操作称为提取操作&#xff0c;而向流中添加数据的操作称为插入操作。 Java IO 也称为IO流&#xff0c;…

QT上位机开发(数据库sqlite编程)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 编写软件的时候&#xff0c;如果用户的数据比较少&#xff0c;那么用json保存是非常方便的。但是一旦数据量大了之后&#xff0c;建议还是用数据库…

计算机网络(8):因特网上的音频/视频服务

概述 计算机网络最初是为传送数据设计的。因特网 IP 层提供的 “尽最大努力交付” 服务以及每一个分组独立交付的策略&#xff0c;对传送数据信息十分合适。因特网使用的 TCP 协议可以很好地解决P层不能提供可靠交付这一问题。 音频/视频常称为多媒体信息 多媒体信息&#xff…

进程与计划任务

什么是程序&#xff1f; 程序&#xff1a;在硬盘上躺着&#xff0c;执行特定任务的一串代码 静态 进程&#xff1a;加载到内存中运行 动态 进程是程序的副本&#xff0c;进程是有生命周期&#xff0c;是硬件资源分配的最小单位 pid号可以通过pstree -p 查到 uid &…

Cytoscape3.8安装下载及安装教程

Cytoscape3.8下载链接&#xff1a;https://docs.qq.com/doc/DUmhZQ1lqTWhuSXJC 1.选中下载好的安装包右键选择“解压到 Cytoscape3.8.0”文件夹 2.打开解压好的”Cytoscape3.8.0“文件夹 3.选中“Cytoscape_3_8_0_windows_64bit.exe“右键以管理员身份运行 4.点击”Download“&…

平衡二叉树,力扣

目录 前序遍历与后续遍历 题目地址&#xff1a; 题目&#xff1a; 我们直接看题解吧&#xff1a; 审题目事例提示&#xff1a; 解题方法&#xff1a; 难度分析&#xff1a; 解题方法分析&#xff1a; 解题分析&#xff1a; 解题思路&#xff1a; 代码实现&#xff1a; 补充说明…

使用jieba库进行中文分词和去除停用词

jieba.lcut jieba.lcut()和jieba.lcut_for_search()是jieba库中的两个分词函数&#xff0c;它们的功能和参数略有不同。 jieba.lcut()方法接受三个参数&#xff1a;需要分词的字符串&#xff0c;是否使用全模式&#xff08;默认为False&#xff09;以及是否使用HMM模型&…

魔术表演Scratch-第14届蓝桥杯Scratch省赛真题第1题

1.魔术表演&#xff08;20分&#xff09; 评判标准&#xff1a; 4分&#xff1a;满足"具体要求"中的1&#xff09;&#xff1b; 8分&#xff1a;满足"具体要求"中的2&#xff09;&#xff1b; 8分&#xff0c;满足"具体要求"中的3&#xff09…

机器学习--ROC AUC

参考 机器学习-ROC曲线 - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/347470776一文看懂ROC、AUC - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/81202617 在了解之前&#xff0c;我们先来认识一下以下的概念 针对一个二分类问题&#xff0c;将实例分成正类(postive)或…

linux-6.0 内核存储栈全景图

linux 存储栈原图地址&#xff1a;https://www.thomas-krenn.com/en/wiki/Linux_Storage_Stack_Diagram

【Linux系统编程二十六】:线程控制与线程特性(Linux中线程库/线程创建/线程退出/线程等待)

【Linux系统编程二十六】&#xff1a;线程控制与线程特性 一.Linux线程库pthread1.线程控制块2.线程tid3.线程栈 二.线程控制1.线程创建2.线程退出3.线程等待 三.线程的特性1.独立栈2.局部存储3.线程可分离 一.Linux线程库pthread 在Linux中&#xff0c;是没有明确的线程概念的…

Sonarqube安装(Docker)

一&#xff0c;拉取相关镜像并运行 # 拉取sonarqube镜像 docker pull sonarqube:9.1.0-community在运行之前要提前安装postgres并允许&#xff0c;新建数据库名为sonar的数据库 Docker安装postgres教程 docker run -d --name sonarqube --restartalways \ -p 19000:9000 \ …

Redis 持久化—RDB

文章目录 1. 为什么需要Redis持久化&#xff1f;2. Redis持久化的几种方式3. RDB简介4. 持久化触发4.1 手动触发4.1.1 save命令4.1.2 bgsave 命令 4.2 自动触发4.2.1 save m n4.2.2 flushall4.2.3 主从同步触发 5. 配置说明6. 配置配置7. 配置配置8. RDB 文件恢复9. RDB 优缺点…

ResNet论文阅读和简单实现

论文&#xff1a;https://arxiv.org/pdf/1512.03385.pdf Deep Residual Learning for Image Recognition 本模块主要是阅读论文&#xff0c;会做简单的翻译&#xff08;至少满足我自己能看明白&#xff09;。 Introduction 由上图可见&#xff0c;在20层和56层的网络上训练的…

深信服技术认证“SCCA-C”划重点:云计算关键技术

为帮助大家更加系统化地学习云计算知识&#xff0c;高效通过云计算工程师认证&#xff0c;深信服特推出“SCCA-C认证备考秘笈”&#xff0c;共十期内容。“考试重点”内容框架&#xff0c;帮助大家快速get重点知识。 划重点来啦 *点击图片放大展示 深信服云计算认证&#xff08…