Linux —— 进程间通信(管道)

news2024/11/14 5:41:05

目录

一,进程间通信

二,管道

匿名管道

命名管道


一,进程间通信

        进程间通信(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/908076.html

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

相关文章

爬虫逆向实战(十九)--某号站登录

一、数据接口分析 主页地址&#xff1a;某号站 1、抓包 通过抓包可以发现登录接口 2、判断是否有加密参数 请求参数是否加密&#xff1f; 通过查看“载荷”模块可以发现有一个jsondata_rsa的加密参数 请求头是否加密&#xff1f; 无响应是否加密&#xff1f; 无cookie是否…

数据分析问答总结

一、SQL窗口函数 1.是什么 OLAP&#xff08;Online Anallytical Processing联机分析处理&#xff09;&#xff0c;对数据库数据进行实时分析处理。 2.基本语法&#xff1a; <窗口函数>OVER &#xff08;PARTITION BY <用于分组的列名> ORDER BY <用于排序的…

【LUBAN】【功能验证】至简投屏功能之Android有线连接方式测试

1、概述 至简投屏功能之Android有线连接方式支持至简自带应用至加的投屏功能和谷歌官方的Android auto功能。 支持的功能范围列举如下&#xff1a; 1、屏幕投屏&#xff08;支持自动旋转屏&#xff09;2、音视频播放&#xff08;抖音、百度地图等&#xff09;3、车机反控手机…

红日靶场(一)vulnstack1 渗透过程分析

文章目录 环境搭建信息收集PhpMyAdmin 后台 Getshellinto outfileMysql日志文件写入shell CS后渗透MSF后渗透知识补充nmap参数分类参数速查表 dirsearch 环境搭建 ip段设置 kali (coleak)&#xff1a;192.168.145.139 Windows 7 (stu1)&#xff1a;192.168.10.181、192.168.1…

报道|新鲜出炉!INFORMS公布六位新任期刊主编

推文作者&#xff1a;徐思坤 编者按 INFORMS旗下的六本期刊&#xff0c;Management Science、Operations Research、Service Science、Tutorials in OR、INFORMS Analytics Collection&#xff0c;以及Transportation Science的新任主编公布&#xff0c;并将于2024年1月1日正式…

linux自动压缩日志文件

目录 前言编写脚本配置计划任务 前言 大型项目日志量非常大&#xff0c;如果不采取特定措施&#xff0c;不到一个月200G的磁盘就会被占满&#xff0c;一种最简单的方法就是将日志文件压缩&#xff0c;使用 tar -cvzf xxx.tar.gz xxx 压缩&#xff0c;压缩后占用空间只有原来的…

Java中Map集合体系{HashMap,TreeMap,LindedHashMap}

Map概述 Map是双列集合&#xff0c;Map集合中的每一个元素是以keyvalue的形式存在的&#xff0c;一个keyvalue就称之为一个键值对&#xff0c;而且在Java中有一个类叫Entry类&#xff0c;Entry的对象用来表示键值对对象。 特点&#xff1a;键不能重复&#xff0c;值可以重复&…

安卓图形显示系统

Android图形显示系统 Android图形显示系统是Android比较重要的一个子系统&#xff0c;和很多其他子系统的关联紧密。 Android图形系统比较复杂&#xff0c;这里我们从整体上理一遍&#xff0c;细节留待后期再去深入。Android图形系统主要包括以下几个方面&#xff1a; - 渲染…

升级Qt后VS项目不能使用

错误场景&#xff1a; 如果你的QT卸载了装了新版,那么VS你原来设置的项目就不能跑了. 问题 升级Qt后&#xff36;&#xff33;项目不能使用 跟我一起开始挽救自己的项目 升级Qt后&#xff36;&#xff33;项目不能使用 假如你从5.14.6 升级到 Qt6.2并删除了原来的QT 你在VS里…

基础论文学习(3)——SwinTransformer

目前Transformer应用到图像领域的挑战&#xff1a; 图像分辨率高&#xff0c;像素点多&#xff0c;如果需要更多特征就必须构建很长的序列&#xff0c;但Transformer基于全局自注意力的计算导致计算量较大&#xff0c;能否用窗口分层的形式代替长序列&#xff0c;实现类似CNN感…

Php“牵手”淘宝商品详情页数据采集方法,淘宝API接口申请指南

淘宝天猫详情接口 API 是开放平台提供的一种 API 接口&#xff0c;它可以帮助开发者获取商品的详细信息&#xff0c;包括商品的标题、描述、图片等信息。在电商平台的开发中&#xff0c;详情接口API是非常常用的 API&#xff0c;因此本文将详细介绍详情接口 API 的使用。 一、…

C语言,Linux,静态库编写方法,makefile与shell脚本的关系。

静态库编写&#xff1a; 编写.o文件gcc -c(小写) seqlist.c(需要和头文件、main.c文件在同一文件目录下) libs.a->去掉lib与.a剩下的为库的名称‘s’。 -ls是指库名为s。 -L库的路径。 makefile文件编写&#xff1a; CFLAGS-Wall -O2 -g -I ./inc/ LDFLAGS-L./lib/ -l…

华为开源自研AI框架昇思MindSpore应用案例:PFLD实时人脸关键点检测算法

目录 一、环境准备1.进入ModelArts官网2.使用CodeLab体验Notebook实例 二、案例实现 人脸关键点检测是一个非常核心的算法业务&#xff0c;其在许多场景中都有应用。比如我们常用的换脸、换妆、人脸识别等2C APP中的功能&#xff0c;都需要先进行人脸关键点的检测&#xff0c;然…

Python随机密码生成。编写程序,在26个字母大小写和10个数字随机生成10个8位密码。

题目&#xff1a;随机密码生成。编写程序&#xff0c;在26个字母大小写和10个数字随机生成10个8位密码。 样例&#xff1a;类似AB12cdHi的十组8位密码。 代码&#xff1a; import random def passwords():a, b, c ord(a), ord(A), ord(1)r list(range(a , a 26)) list(ra…

Comparable和Comparator区别

Comparable和Comparator接口都是实现集合中元素的比较、排序的&#xff0c;众所周知&#xff0c;诸如Integer&#xff0c;double等基本数据类型&#xff0c;java可以对他们进行比较&#xff0c;而对于类的比较&#xff0c;需要人工定义比较用到的字段比较逻辑。总体来讲&#x…

电脑找不到vcruntime140.dll文件怎么解决?教你解决这个问题

​vcruntime140.dll是Microsoft Visual C 2015 Redistributable Package中的一个文件&#xff0c;它包含了运行C应用程序所需的运行时库。如果在计算机上找不到这个文件&#xff0c;可能会导致一些应用程序无法正常运行。本文将介绍如何修复vcruntime140.dll丢失的问题以及一些…

【计算机网络八股】计算机网络(一)

目录 计算机网络的各层协议及作用&#xff1f;TCP和UDP的区别&#xff1f;UDP 和 TCP 对应的应用场景是什么&#xff1f;详细介绍一下 TCP 的三次握手机制&#xff1f;为什么需要三次握手&#xff0c;而不是两次&#xff1f;为什么要三次握手&#xff0c;而不是四次&#xff1f…

鼠标拖拽盒子移动

目录 需求思路代码页面展示【补充】纯js实现 需求 浮动的盒子添加鼠标拖拽功能 思路 给需要拖动的盒子添加鼠标按下事件鼠标按下后获取鼠标点击位置与盒子边缘的距离给 document 添加鼠标移动事件鼠标移动过程中&#xff0c;将盒子的位置进行重新定位侦听 document 鼠标弹起&a…

线性代数的学习和整理7:各种特殊效果矩阵特例(草稿-----未完成)

目录 1 矩阵 1.1 1维的矩阵 1.2 2维的矩阵 1.3 没有3维的矩阵---3维的是3阶张量 2 方阵 3 单位矩阵 3.1 单位矩阵的定义 3.2 单位矩阵的特性 3.3 为什么单位矩阵I是 [1,0;0,1] 而不是[0,1;1,0] 或[1,1;1,1] 3.4 零矩阵 3.4 看下这个矩阵 [0,1;1,0] 3.5 看下这个矩阵…

很好的启用window10专业版系统自带的远程桌面

启用window10专业版系统自带的远程桌面 文章目录 启用window10专业版系统自带的远程桌面前言1.找到远程桌面的开关2. 找到“应用”项目3. 打开需要远程操作的电脑远程桌面功能 总结 前言 Windows操作系统作为应用最广泛的个人电脑操作系统&#xff0c;在我们身边几乎随处可见。…