Linux —— 进程间通信

news2025/1/13 3:06:32

目录

一,进程间通信

二,管道

匿名管道

命名管道


一,进程间通信

        进程间通信(IPC,InterProcess Communication),即在不同进程之间进行信息的传播或交换;由于一般进程用户地址空间是独立的,不可直接访问其他进程地址空间,因此进程间进行信息交换必须通过系统内核进行;

进程间通信目的

  • 数据传输,将一个进程的数据发送给另一个进程;
  • 资源共享,多个进程间共享同样的资源;
  • 通知事件,一个进程向另一个进程或一组进程发送信息,通知它们发生了某种事件(如进程终止时通知父进程);
  • 进程控制,有些进程希望完全控制另一个进程的执行(如debug),此时进程希望能够拦截另一个进程的所有异常,并能够及时知道其状态的改变;

进程间通信的分类

  • 管道
    • 匿名管道pipe
    • 命名管道
  • System V IPC
    • system V 消息队列
    • system V 共享内存
    • system V 信号量
  • POSIX IPC
    • 信息队列
    • 共享内存
    • 信息量
    • 互斥量
    • 调节变量
    • 读写锁

二,管道

        匿名管道pipe、命名管道;

匿名管道

        Linux通过使用竖线(管道符 | )来连接多个命令,以形成一个管道;管道符前面命令的输出作为管道符后面命令的输入,管道中的数据只能单向流动(即半双工通信),要实现双向流动需创建两个管道;另外,此管道为匿名管道,用完即被自动销毁,且只能在父子进程间通信;

[wz@192 Desktop]$ cat test.c | grep main
int main() 

        父进程需读写都打开文件,这样子进程继承时才会有读写,然后通过关闭父子进程对应的读写,来实现信息的传输;不关闭相应的读写,也可通信,但一般关闭防止误操作;

管道函数 pipe

  • 创建匿名管道
    • 创建成功,返回0;
    • 创建失败,返回-1;

pipefd为文件描述符数组

  • pipefd[0],指定管道读端,默认值为3;
  • pipefd[1],指定管道写端,默认值为4;
#include <stdio.h>    
#include <unistd.h>    
    
int main()    
{    
  int pipefd[2];    
  if(pipe(pipefd) < 0)    
  {    
    perror("pipe");                                                                   
    return 1;    
  }    
  printf("pipefd[0]: %d\n", pipefd[0]);    
  printf("pipefd[1]: %d\n", pipefd[1]);    
  return 0;    
}   
[wz@192 pipe]$ ./test
pipefd[0]: 3
pipefd[1]: 4
int main()      
{      
  int pipefd[2];      
  if(pipe(pipefd) < 0){      
    perror("pipe");      
    return 1;      
  }      
  char buf[32];      
  write(pipefd[1],"hellopipe",32); //向管道内写
  read(pipefd[0],buf,32); //从管道内读     
  printf("buf: %s\n", buf);                                                           
  return 0;      
}   
[wz@192 pipe]$ ./test 
buf: hellopipe

//子进程写入,父进程读取                                                                                     
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
  
int main()
{
    int pipefd[2];
    if(pipe(pipefd) < 0){
        perror("pipe");
        return 1;
    }
  
    pid_t id = fork();
    if(id < 0){
        perror("fork");
        return 1;
    }
  
    else if(id == 0){
        close(pipefd[0]);
        char* msg = "child msg";
        int count=5;
        while(count){
            printf("child write: %s\n",msg);
            write(pipefd[1],msg,strlen(msg));
            sleep(1);
            count--;
       }
       close(pipefd[1]);
       exit(0);
    }
    
    else{
        char buf[64];
        close(pipefd[1]);
        while(1){
            ssize_t sz=read(pipefd[0],buf,sizeof(buf)-1);
            if(sz>0){
                buf[sz]=0;
                printf("father read: %s\n",buf);
            }
            else if(sz==0){
                printf("pipe file empty!\n");
                break;
            }
        }
        close(pipefd[0]);
        printf("close read\n");

        int status = 0;    
        pid_t wait_pid = waitpid(id,&status,0);    
        if(WIFEXITED(status) && wait_pid==id)    
            printf("child exit normal, exit code: %d\n", WEXITSTATUS(status));    
        else     
            printf("child exit error, exit sig: %d\n", WTERMSIG(status));  
    }
    return 0;
}
  • 如管道为空,则读端需等待数据就绪,即read阻塞;
  • 如管道在写端已写满,需等待管道有空闲空间才可继续写入,即write阻塞;
  • 管道自带同步机制;
  • 管道是单向通信的;
  • 管道是面向字节流的;
  • 管道只能保证具有血缘关系的进程通信;
  • 管道可保证一定程度数据读取的原子性;
//子进程持续在写入,父进程关闭读
//此时OS会直接关闭子进程
    else{
        char buf[64];
        close(pipefd[1]);
        while(1){
            ssize_t sz=read(pipefd[0],buf,sizeof(buf)-1);
            if(sz>0){
                buf[sz]=0;
                printf("father read: %s\n",buf);
                close(pipefd[0]);
                break;
            }
            else if(sz==0){
                printf("pipe file empty!\n");
                break;
            }
        }
        printf("close read\n");

        int status = 0;    
        pid_t wait_pid = waitpid(id,&status,0);    
        if(WIFEXITED(status) && wait_pid==id)    
            printf("child exit normal, exit code: %d\n", WEXITSTATUS(status));    
        else     
            printf("child exit error, exit sig: %d\n", WTERMSIG(status));  
    }
//子进程退出信号为13,即SIGPIPE
[wz@192 pipe]$ ./test 
child write: child msg
father read: child msg
close read
child write: child msg
child exit error, exit sig: 13
[wz@192 pipe]$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 7154
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 4096
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

命名管道

        命名管道是一种特殊类型的文件,可在不相关进程间交换数据,使用FIFO文件实现;

使用命令mkfifo,创建命名管道

[wz@192 pipe]$ mkfifo pipefile
[wz@192 pipe]$ ll pipefile
prw-rw-r--. 1 wz wz 0 8月  18 08:24 pipefile

使用函数mkfifo,创建命名管道

匿名管道与命名管道区别

  • 匿名管道由函数pipe创建并打开;
  • 命名管道由函数或命令mkfifo创建,再由open打开;
  • 唯一区别即创建和打开方式不同;
[wz@192 pipe]$ echo abc > pipefile 
[wz@192 pipe]$ while :; do echo "1,##########"; cat pipefile; echo "2,#########"; sleep 1; done
1,##########
abc
2,#########
1,##########

实现server&client通信

//makefile
.PHONY:all
all: server client
    
server:server.c
  gcc -o $@ $^    
client:client.c
  gcc -o $@ $^    
    
.PHONY:clean
clean:
  rm -rf server client  
//server.c 
//创建命名管道,并读
#include <stdlib.h>    
#include <string.h>    
#include <unistd.h>    
#include <sys/types.h>    
#include <sys/stat.h>    
#include <fcntl.h>    
    
int main()    
{    
  int ret = mkfifo("pipefile", 0644);    
  if(ret == -1){    
    perror("mkfifo");    
    return 1;    
  }    
  int pipefd = open("pipefile", O_RDONLY);    
  if(pipefd < 0){    
    perror("open");    
    return 2;    
  }    
  char msg[64]={0};    
  while(1){    
    printf("please wait ...\n");    
    ssize_t sz = read(pipefd, msg, sizeof(msg)-1);    
    if(sz > 0){    
      msg[sz]=0;    
      printf("server read: %s\n", msg);                                                                        
    }    
    else if(sz == 0){    
      printf("client quit!\n");    
      break;    
    }    
    else{    
      perror("read");    
      return 3;    
    }    
  }    
  close(pipefd);    
  return 0;    
}  
//client.c
//向管道写入
#include <stdlib.h>    
#include <string.h>    
#include <unistd.h>    
#include <sys/types.h>    
#include <sys/stat.h>    
#include <fcntl.h>    
    
int main()    
{    
  int pipefd = open("pipefile", O_WRONLY);    
  if(pipefd < 0){    
    perror("open");    
    return 1;    
  }    
    
  char msg[64]={0};    
  while(1){    
    printf("please write ...\n");    
    ssize_t sz = read(0, msg, sizeof(msg)-1);    
    if(sz > 0){    
      msg[sz]=0;    
      write(pipefd, msg, strlen(msg));    
    }    
    else if(sz == 0){    
      printf("client read empty!\n");    
      break;    
    }    
    else{    
      perror("client read\n");    
      return 2;    
    }                                                                                                          
  }    
  close(pipefd);    
  return 0;    
} 

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

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

相关文章

C++ STL容器适配器(详解)

STL容器适配器 什么是适配器&#xff0c;C STL容器适配器详解 在详解什么是容器适配器之前&#xff0c;初学者首先要理解适配器的含义。 其实&#xff0c;容器适配器中的“适配器”&#xff0c;和生活中常见的电源适配器中“适配器”的含义非常接近。我们知道&#xff0c;无…

Python土力学与基础工程计算.PDF-螺旋板载荷试验

python 求解代码如下&#xff1a; 1. import numpy as np 2. 3. # 已知参数 4. p_a 100 # 标准压力&#xff0c; kPa 5. p np.array([25, 50, 100, 200) # 荷载&#xff0c; kPa 6. s np.array([2.88, 5.28, 9.50, 15.00) / 10 # 沉降量&#xff0c; cm 7. D 10 # 螺旋板直…

opencv直方图与模板匹配

import cv2 #opencv读取的格式是BGR import numpy as np import matplotlib.pyplot as plt#Matplotlib是RGB %matplotlib inline def cv_show(img,name):cv2.imshow(name,img)cv2.waitKey()cv2.destroyAllWindows() 直方图 cv2.calcHist(images,channels,mask,histSize,ran…

2023-8-18 最长连续不重复子序列

题目链接&#xff1a;最长连续不重复子序列 #include <iostream>using namespace std;const int N 100010; int n; int a[N], s[N];int main () {cin >> n;for(int i 0; i < n; i ) cin >> a[i];int res 0;for(int i 0, j 0; i < n; i){s[a[i]];w…

jenkins 是什么?

一、jenkins 是什么&#xff1f; Jenkins是一个开源的、提供友好操作界面的持续集成(CI)工具&#xff0c;起源于Hudson&#xff0c;主要用于持续、自动的构建/测试软件项目、监控外部任务的运行。Jenkins用Java语言编写&#xff0c;可在Tomcat等流行的servlet容器中运行&#…

集简云 x 车邻邦丨实现金蝶云星辰快速集成第三方系统,实现单据自动同步

品牌故事 车邻邦成立于2009年&#xff0c;专注于汽车贴膜及美容装饰服务&#xff0c;核心业务是为高端4S店、4S集团提供汽车精品领域“产品营销施工售后”的一站式解决方案。 公司成立至今已有14年之久&#xff0c;累计服务客户数百家、累计服务车辆百万台次&#xff0c;口碑…

windows结束explorer进程后桌面白屏解决

背景 结束进程时一不小心一起删掉explorer.exe &#xff0c;这个文件结束桌面就一片白 &#xff0c; 解决&#xff1a; 不要关机&#xff0c;同时按键盘上ctrlshiftesc ,重新进入任务管理器&#xff0c;接着点“进程”选项&#xff0c;按左上角文件选项&#xff0c;进入下拉菜单…

2023年Java核心技术面试第二篇(篇篇万字精讲)

目录 四. 强引用&#xff0c;软引用&#xff0c;弱引用&#xff0c;幻象引用之间的区别&#xff1f; 1.前言 2.强引用 2.1 强引用赋值为null 2.2 超过了引用的作用域 2.2.1 描述&#xff1a; 2.2.2 作用域内&#xff1a; 2.2.3 不在作用域内: 3. 软引用&#xff08;SoftRefere…

助力工业物联网,工业大数据之服务域:服务器性能监控Prometheus及项目总结【三十五】

服务器性能监控Prometheus及项目总结 01&#xff1a;目标 服务器性能监控工具 整体作为了解实现部署安装以及监控构建 项目总结 需求分析、技术架构数仓设计&#xff1a;主题划分、分层设计、维度设计优化、问题、数据量及集群规模简历模板 02&#xff1a;监控需求及常见工…

Cat(6):API介绍—Metric

Metric 用于记录业务指标、指标可能包含对一个指标记录次数、记录平均值、记录总和&#xff0c;业务指标最低统计粒度为1分钟。 # Counter Cat.logMetricForCount("metric.key"); Cat.logMetricForCount("metric.key", 3); # Duration Cat.logMetricForDu…

java学习004

常用数据结构对应 php中常用的数据结构是Array数组&#xff0c;相对的在java开发中常用的数据结构是ArrayList和HashMap&#xff0c;它们可以看成是array的拆分&#xff0c;一种简单的对应关系为 PHPJAVAArray: array(1,2,3)ArrayListlArray: array(“name” > “jack”,“…

通过请求头传数据向后端发请求

axios &#xff08;get post请求、头部参数添加&#xff09;傻瓜式入门axios_axiospost请求参数_web_blog的博客-CSDN博客

【第八讲---视觉里程计2】

在图像中提取特征点并计算特征描述&#xff0c;非常耗时 通过计算描述子距离在不同图像中寻找特征匹配&#xff0c;也非常耗时 利用通过匹配点信息计算相机位姿&#xff0c;没什么问题 我们可以采用以下方法进行改进&#xff1a; 光流&#xff1a;通过其他方式寻找匹配点直接法…

原型对象的简单了解

在前面学习java有一个概念叫做继承&#xff0c;方便我们对父类方法、变量等的调用。对前端的学习我们需要让对象可以访问和继承其他对象的属性和方法&#xff0c;就需要了解原型对象&#xff0c;以及原型链。 一、原型 构造函数通过原型分配的函数是所有对象所共享的。每一个构…

SpringBoot Vue 微人事(十)

职位管理前后端对接问题解决 因为mysql字段关联其他表&#xff0c;进行约束了&#xff0c;删除不了的&#xff0c;就报未知错误是不合适的 需要在后端写一个全局异常类 删掉了MySQLIntegrityConstraintViolationException这个异常类才能导包&#xff0c;能用 RestController…

AutoSAR系列讲解(深入篇)13.6-Mcal Mcu时钟的配置

目录 一、EB的Mcu模块结构 二、时钟的配置 对Mcu的配置主要就是其时钟树的配置,但是EB将GTM、ERU等很多重要的模块也都放在了Mcu里面做配置,所以这里的Mcu是一个很庞大的模块, 我们目前只讲时钟树的部分 一、EB的Mcu模块结构 1. 所有的模块都基本上是这么些配置类别,Mc…

Spark 图计算ONEID 进阶版

0、环境信息 本文采用阿里云maxcompute的spark环境为基础进行的&#xff0c;搭建本地spark环境参考搭建Windows开发环境_云原生大数据计算服务 MaxCompute-阿里云帮助中心 版本spark 2.4.5&#xff0c;maven版本大于3.8.4 ①配置pom依赖 详见2-1 ②添加运行jar包 ③添加配置信…

SAP SQL/CDS新功能货币汇率转换CURRENCY_CONVERSION( p1 = a1, p2 = a2, … )

1. 示例 PARAMETERS: p_waers TYPE mseg-waers OBLIGATORY DEFAULT USD.SELECT SUM( currency_conversion( amount a~hsl, "转换的金额source_currency b~isocd, "源货币target_currency p_waers, "目标货币exchange_rate_dat…

ClickHouse(二十一):Clickhouse SQL DDL操作-临时表及视图

进入正文前&#xff0c;感谢宝子们订阅专题、点赞、评论、收藏&#xff01;关注IT贫道&#xff0c;获取高质量博客内容&#xff01; &#x1f3e1;个人主页&#xff1a;含各种IT体系技术&#xff0c;IT贫道_Apache Doris,大数据OLAP体系技术栈,Kerberos安全认证-CSDN博客 &…

Bean 作用域、生命周期和Spring执行流程

文章目录 Bean作用域问题案例分析公共 BeanA 用户使用时修改B 用户使用时原因分析 作用域定义Bean 的6种作用域singletonprototyperequestsessionapplicationwebsocket 设置作用域 Spring 执行流程1、启动容器2、Bean 初始化3、注册Bean对象到容器中4、装配Bean属性 Bean 生命周…