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

Linux:进程间通信(1)

目录

​编辑

1.进程间通信

1.1进程间通信目的

1.2.进程间通信发展

1.3.进程间通信分类

2.管道

3.匿名管道

3.1实例代码

3.2⽤fork来共享管道原理

3.3站在文件描述符角度-深度理解管道

3.4站在内核角度-管道本质

3.5管道样例

3.6管道读写规则

3.7管道特点

4.命名管道

4.1创建⼀个命名管道

4.2匿名管道与命名管道的区别

4.3命名管道的打开规则

4.4综合实例


1.进程间通信

1.1进程间通信目的

• 数据传输:实现进程间的数据交换与共享

• 资源共享:允许多个进程共同访问相同资源

• 事件通知:当特定事件发生时,向目标进程发送提醒信息(如进程终止时通知父进程)

• 进程控制:支持主控进程对目标进程的全方位监管(如调试进程),包括拦截异常、监控状态变更等

1.2.进程间通信发展

  • 管道(Pipes)
  • SystemV 进程间通信
  • POSIX 进程间通信

接下来我们进程通信将围绕这三个来讲解!!!!

1.3.进程间通信分类

通信机制:

  1. 管道通信:

    • 匿名管道(pipe)
    • 命名管道
  2. SystemV IPC机制:

    • 消息队列
    • 共享内存
    • 信号量
  3. POSIX IPC机制:

    • 消息队列
    • 共享内存
    • 信号量
    • 互斥量
    • 条件变量
    • 读写锁

2.管道

什么是管道?

  • 管道是Unix系统中最古老的进程间通信机制。
  • 它指的是连接两个进程的数据流。

3.匿名管道

int pipe(int fd[2]);

功能 : 创建⼀⽆名管道

其头文件:

#include <unistd.h>

参数说明:

  • fd:文件描述符数组
    • fd[0] 表示读端
    • fd[1] 表示写端

返回值:

  • 成功:返回0
  • 失败:返回错误代码

3.1实例代码

从键盘获取输入数据后,将数据写入管道,再从管道读取数据并输出到显示器。

#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>int main()
{int fd[2] = {0};if(pipe(fd)<0) //创建管道{perror("pipe err");exit(1);}char buf[100];int len;while(fgets(buf,100,stdin)){len = strlen(buf);if( write(fd[1], buf, len) != len ) //写数据到管道{perror("write err");break;}memset(buf, 0x00, sizeof(buf));if ( (len=read(fds[0], buf, 100)) == -1 ) { //从管道中读取数据perror("read from pipe");break;}if ( write(1, buf, len) != len ) { //将读取的数据写到屏幕上perror("write to stdout");break;}}return 0;
}

3.2⽤fork来共享管道原理

3.3站在文件描述符角度-深度理解管道

3.4站在内核角度-管道本质

在Linux系统中,管道的使用方式与文件操作完全一致,完美体现了"Linux一切皆文件"的设计理念。

3.5管道样例

    1   #include <unistd.h>2  #include <stdlib.h>3  #include <stdio.h>4  #include <errno.h>5  #include <string.h>6  #define ERR_EXIT(m) \7  do \8  { \9  perror(m); \10  exit(EXIT_FAILURE); \11  } while(0)12  int main(int argc, char *argv[])13  {                                                                                                                                                                                                                             14  int pipefd[2];15  if (pipe(pipefd) == -1)16  ERR_EXIT("pipe error");17  pid_t pid;18  pid = fork();19  if (pid == -1)20  ERR_EXIT("fork error");21  if (pid == 0) {22  close(pipefd[0]);23  write(pipefd[1], "hello", 5);24  close(pipefd[1]);25  exit(EXIT_SUCCESS);26  }27  close(pipefd[1]);28  char buf[10] = {0};29  read(pipefd[0], buf, 10);30  printf("buf=%s\n", buf);31  return 0;32  }

执行后的结果:

3.6管道读写规则

• 无数据可读时:

◦ O_NONBLOCK关闭:read调用会阻塞进程,直到有数据到达

◦ O_NONBLOCK开启:read调用立即返回-1,并设置errno为EAGAIN

• 管道已满时:

◦ O_NONBLOCK关闭:write调用会阻塞,直到其他进程读取数据

◦ O_NONBLOCK开启:write调用立即返回-1,并设置errno为EAGAIN

• 管道状态影响:

◦ 所有写端关闭时:read调用返回0

◦ 所有读端关闭时:write调用会触发SIGPIPE信号,可能导致进程终止

• 写入原子性保证:

◦ 数据量≤PIPE_BUF:Linux保证写入操作的原子性

◦ 数据量>PIPE_BUF:Linux不保证写入操作的原子性

3.7管道特点

• 仅适用于具有亲缘关系的进程间通信,通常由父进程创建管道后调用fork,实现父子进程间的数据传输

• 采用流式数据传输机制

(采用流式数据传输机制是一种高效的数据传输方式,它允许数据在发送方和接收方之间连续、实时地流动,而无需等待整个数据集完全传输完毕。这种机制特别适用于需要低延迟和大规模数据处理的场景,如视频流、实时监控、在线游戏和金融交易等。)

• 管道的生命周期与进程绑定,进程终止时自动释放

• 内核默认对管道操作实施同步与互斥管理

• 管道采用半双工通信模式,双向通信需建立两条独立管道

4.命名管道

• 管道应用存在一个主要限制:只能在具有共同祖先(即存在亲缘关系)的进程间进行通信。

• 要在不相关进程间交换数据,可以使用FIFO文件(也称为命名管道)来实现。

• 命名管道属于一种特殊类型的文件。

4.1创建⼀个命名管道

命名管道可以通过命令行创建,具体操作是执行以下命令:

 mkfifo filename

程序内部可以通过特定函数创建命名管道,常用的相关函数包括:

int mkfifo(const char *filename,mode_t mode);

创建命名管道:

创建好的管道(p1):

注意:

  1. 实际创建的文件权限会受到umask(文件默认掩码)的影响,最终权限计算公式为:mode & (~umask)。umask默认值通常为0002。例如,当mode设置为0666时,最终创建的文件权限将是0664。(所以我们开头就将umask值设置为0,这样就不会影响到我们权限的赋予)

  2. 管道文件类型标识符以字母"p"开头。

4.2匿名管道与命名管道的区别

• 匿名管道通过pipe函数创建并开启。

• 命名管道由mkfifo函数创建,使用open函数开启。

• 命名管道(FIFO)和匿名管道(pipe)的主要区别仅在于创建和开启方式不同,完成这些操作后,两者的行为特性完全一致。

4.3命名管道的打开规则

• 如果当前打开操作是为读⽽打开FIFO时:

◦ O_NONBLOCK disable:阻塞直到有相应进程为写⽽打开该FIFO

◦ O_NONBLOCK enable:⽴刻返回成功

• 如果当前打开操作是为写⽽打开FIFO时:

◦ O_NONBLOCK disable:阻塞直到有相应进程为读⽽打开该FIFO

◦ O_NONBLOCK enable:⽴刻返回失败,错误码为ENXIO

4.4综合实例

1.用命名管道实现文件拷贝:

读取文件内容并写入命名管道:

 #include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#include <string.h>#include <fcntl.h>#define ERR_EXIT(m) \do \{ \perror(m); \exit(EXIT_FAILURE); \} while(0)
int main(int argc, char *argv[]){mkfifo("tp", 0644);int infd;infd = open("abc", O_RDONLY);if (infd == -1) ERR_EXIT("open");int outfd;outfd = open("tp", O_WRONLY);if (outfd == -1) ERR_EXIT("open");char buf[1024];int n;while ((n=read(infd, buf, 1024))>0){write(outfd, buf, n);}close(infd);close(outfd);return 0;}  

读取管道数据并写入目标文件:

 #include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#include <string.h>#include <fcntl.h>#define ERR_EXIT(m) \do \{ \perror(m); \exit(EXIT_FAILURE); \} while(0)int main(int argc, char *argv[]){int outfd;outfd = open("abc.bak", O_WRONLY | O_CREAT | O_TRUNC, 0644);if (outfd == -1) ERR_EXIT("open");int infd;infd = open("tp", O_RDONLY);if (outfd == -1)ERR_EXIT("open");char buf[1024];int n;while ((n=read(infd, buf, 1024))>0){write(outfd, buf, n);}close(infd);close(outfd);unlink("tp");return 0;}

2.用命名管道实现server&client通信:

在搭建客户端之前,需要先建立服务端并创建通信管道。具体实现方式是:服务端以读取模式从管道接收数据,而客户端则以写入模式向管道发送数据。

comm.h:(因为客户端和服务端的头文件相同所以我们只用打一遍就行,到时候引用comm.h就行)

server:

client:

运行起来后的结果如下:

从上述实例可以看出,命名管道能够实现两个独立进程之间的通信连接。

本节先到此结束,如过对进程通信感兴趣的话,还有后续进程通信(2)可以去看看哦!!!!

http://www.dtcms.com/a/519639.html

相关文章:

  • 基于ORB-SLAM、A*及DWA的自主导航方案
  • 阜新网站开发公司dede手机网站建设教程
  • 网站搭建价格宁波网站优化技术
  • 达梦数据库怎么查看连接情况
  • UVa1497/LA5719 A Letter to Programmers
  • 谷歌Quantum Echoes算法:迈向量子计算现实应用的重要一步
  • 网络管理员教程(初级)第六版--第2章 局域网技术
  • PY32F040单片机介绍(1)
  • 数据库多表关系、查询与约束
  • 空调设备公司网站建设建设部网站社保联网
  • 济源网站建设电话锦州做网站的个人
  • 逻辑推演题——谁是骗子
  • 单位网站建设汇报材料wordpress菜单保存不
  • 【底层机制】【Android】Android 系统的启动流程
  • js基础:06、函数(创建函数、参数、返回值、return、立即执行函数、对象(函数))和枚举对象的属性
  • LeetCode 刷题【131. 分割回文串】
  • 7. Functions(函数)
  • 零基础掌握 Vanna Text2SQL 框架:从原理到实战训练指南
  • [linux仓库]信号处理及可重入函数[进程信号·陆]
  • webrtc源码走读(一)-QOS-NACK-概述
  • wordpress 企业网站 免费如何注册网站免费的
  • 斗地主游戏源码,自适应手机版,带有管理后端
  • Linux桌面X11服务-XRecord方案捕获鼠标点击的应用窗口
  • 021数据结构之并查集——算法备赛
  • 网站制作售后免费在线代理网站
  • Vue组件的一些底层细节
  • 2. =>的用法 C#例子 WPF例子
  • 在C#中出现WinForm原控件Chart卡顿问题
  • Spring Boot 3零基础教程,WEB 开发 内嵌服务器底层源码分析 笔记48
  • 网站开发案例分析成都制作网页