当前位置: 首页 > ops >正文

linux-------------------------进程间通信(上)

1.进程间通信介绍

1-1 进程间通信目的

数据传输:一个进程需要把数据传输给另外一个进程

资源共享:多个进程可以共享资源

通知事件:一个进程需要通知另外多个或者一个进程比如子进程结束时要通知父进程进行回收

进程控制:有些进程希望完全控制另⼀个进程的执⾏(如Debug进程),此时控制进程希望能够
拦截另⼀个进程的所有陷⼊和异常,并能够及时知道它的状态改变。

1-2 进程间通信发展

1.管道

2.System V进程间通信

3.POSIX进程间通信

1-3 进程间通信分类

管道
匿名管道pipe
命名管道
System V
消息队列
共享内存
信号量
POSIX
消息队列
共享内存
信号量
互斥量
条件变量
读写锁

2 管道

什么是管道
管道是unix中最古老的进程间通信方式
我们把从一个进程连接到另一个进程的一个数据流称为管道

3匿名管道

3-1 代码实例

#include <iostream>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <cstring>
using namespace std;int main(void)
{int fds[2];char buf[100];int len;if (pipe(fds) == -1)perror("make pipe"), exit(1);// read from stdinwhile (fgets(buf, 100, stdin)){len = strlen(buf);// write into pipeif (write(fds[1], buf, len) != len){perror("write to pipe");break;}memset(buf, 0x00, sizeof(buf));// read from pipeif ((len = read(fds[0], buf, 100)) == -1){perror("read from pipe");break;}// write to stdoutif (write(1, buf, len) != len){perror("write to stdout");break;}}
}

3-2 用fork来共享管道原理

3-3 站在⽂件描述符⻆度-深度理解管道

3-4 站在内核⻆度-管道本质

3-5 管道样例

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#define ERR_EXIT(m)         \do                      \{                       \perror(m);          \exit(EXIT_FAILURE); \} while (0)
int main(int argc, char *argv[])
{int pipefd[2];if (pipe(pipefd) == -1)ERR_EXIT("pipe error");pid_t pid;pid = fork();if (pid == -1)ERR_EXIT("fork error");if (pid == 0){close(pipefd[0]);write(pipefd[1], "hello", 5);close(pipefd[1]);exit(EXIT_SUCCESS);}close(pipefd[1]);char buf[10] = {0};read(pipefd[0], buf, 10);printf("buf=%s\n", buf);return 0;
}

3-6 管道读写规则

1.读操作

  • 管道中有数据

    • read()立即返回可用数据(最多达到请求的大小)

    • 实际读取字节数 ≤ 请求字节数

  • 管道为空

    • 写端全部关闭:read()返回0(EOF)

    • 写端未关闭:read()阻塞等待数据

2.写操作

  • 管道有空间

    • write()立即执行,写入所有请求的数据

  • 管道空间不足

    • 读端全部关闭:write()会触发SIGPIPE信号

    • 读端未关闭:write()阻塞直到有足够空间

3-7 管道特点

只能⽤于具有共同祖先的进程(具有亲缘关系的进程)之间进⾏通信;通常,⼀个管道由⼀个进
程创建,然后该进程调⽤fork,此后⽗、⼦进程之间就可应⽤该管道。
管道提供流式服务
⼀般⽽⾔,进程退出,管道释放,所以管道的⽣命周期随进程
⼀般⽽⾔,内核会对管道操作进⾏同步与互斥
管道是半双⼯的,数据只能向⼀个⽅向流动;需要双⽅通信时,需要建⽴起两个管道

4 命名管道

核心特性

  1. 文件系统可见:在文件系统中有一个路径名(如 /tmp/myfifo

  2. 进程无关性:任何有权限的进程都可以访问

  3. 持久性:文件系统存在直到被显式删除

  4. 半双工通信:数据单向流动(需要双向通信时需创建两个FIFO)

  5. 阻塞特性:默认情况下,打开FIFO会阻塞直到另一端也被打开

创建与使用

创建方法

Shell命令创建

mkfifo /path/to/fifo

C语言创建

#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);

代码演示

写入端:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>#define FIFO_PATH "/tmp/myfifo"
#define BUFFER_SIZE 128int main() {// 创建FIFO(如果已存在则忽略)if (mkfifo(FIFO_PATH, 0666) == -1 && errno != EEXIST) {perror("mkfifo failed");exit(EXIT_FAILURE);}printf("Writer: Opening FIFO...\n");int fd = open(FIFO_PATH, O_WRONLY);  // 阻塞直到有读取端打开if (fd == -1) {perror("open failed");exit(EXIT_FAILURE);}printf("Writer: FIFO opened\n");const char *message = "Hello from writer process!";printf("Writer: Sending message: %s\n", message);if (write(fd, message, strlen(message)) == -1) {perror("write failed");close(fd);exit(EXIT_FAILURE);}close(fd);printf("Writer: Closed FIFO\n");// 可选:删除FIFO文件// unlink(FIFO_PATH);return EXIT_SUCCESS;
}

读取端:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>#define FIFO_PATH "/tmp/myfifo"
#define BUFFER_SIZE 128int main() {printf("Reader: Opening FIFO...\n");int fd = open(FIFO_PATH, O_RDONLY);  // 阻塞直到有写入端打开if (fd == -1) {perror("open failed");exit(EXIT_FAILURE);}printf("Reader: FIFO opened\n");char buffer[BUFFER_SIZE];ssize_t bytes_read = read(fd, buffer, BUFFER_SIZE - 1);if (bytes_read == -1) {perror("read failed");close(fd);exit(EXIT_FAILURE);}buffer[bytes_read] = '\0';  // 添加字符串终止符printf("Reader: Received message: %s\n", buffer);close(fd);printf("Reader: Closed FIFO\n");// 删除FIFO文件if (unlink(FIFO_PATH) == -1) {perror("unlink failed");exit(EXIT_FAILURE);}printf("Reader: FIFO file deleted\n");return EXIT_SUCCESS;
}

与匿名管道的比较

特性匿名管道命名管道 (FIFO)
文件系统可见
进程关系要求必须有亲缘关系无要求
创建方式pipe() 系统调用mkfifo() 函数
生命周期随进程结束显式删除
访问控制文件权限控制
双向通信需要两个管道需要两个FIFO
阻塞行为内置可配置
http://www.xdnf.cn/news/12177.html

相关文章:

  • QMetaObject::invokeMethod调用失败
  • 摄像机ISP处理流程
  • 【面经分享】京东
  • springboot实现查询学生
  • Spring @Scheduled vs XXL-JOB vs DolphinScheduler vs Airflow:任务调度框架全景对比
  • 电子电路:什么是扩散电容?
  • PC 360安全浏览器
  • Spring Boot + MyBatis 集成支付宝支付流程
  • Hive的Parquet格式优化方法
  • AI应用工程师面试
  • html+css+js趣味小游戏~MissileGame街机挑战(附源码)
  • Hive SQL常见操作
  • 人工智能--大型语言模型的存储
  • 窗口聚合窗口聚合
  • YOLOv11 | 注意力机制篇 | 混合局部通道注意力MLCA与C2PSA机制
  • 【photoshop】专色浓度和专色密度
  • Python[数据结构及算法 --- 栈]
  • Mobile App UI自动化locator
  • 【数据结构】树形结构--二叉树(二)
  • JavaSec-XSS
  • 深入理解Java多态性:原理、实现与应用实例
  • SpringBoot使用dynamic配置多数据源时使用@Transactional事务在非primary的数据源上遇到的问题
  • 基于LocalAI与cpolar技术协同的本地化AI模型部署与远程访问方案解析
  • 通过SAE实现企业应用的云上托管
  • CICD实战(一) -----Jenkins的下载与安装
  • 数据可视化大屏项目怎么做?捷码平台5步实施框架
  • 从零到一:Maven 快速入门教程
  • 从零开始的嵌入式学习day33
  • 肿瘤相关巨噬细胞(TAM)
  • 新成果:GaN基VCSEL动态物理模型开发