系统编程-管道

news2024/9/21 4:27:51

管道

目录

管道

1、管道的特点

2、无名管道的使用步骤

(1)在进程中使用 pipe 函数来获取管道的文件描述符

(2)使用 fork 函数来创建子进程

(3)通过获取到的文件描述符来进行数据的传输

(4)当管道不再使用的时候 需要进行关闭

3、有名管道的使用步骤

(1)创建一个有名管道出来

(2)打开有名管道 (有名管道的使用方式)

(3)通过打开的有名管道进行数据的操作

(4)关闭有名管道

4、删除有名管道函数

使用有名管道实现双向通信,用两根管道


引入:

  • 信号可以实现进程间的交互 但是没法发送数据。

  • 管道可以实现数据的传输

  • linux 下一切都是文件,管道也是一种文件 我们可以通过文件操作来进行数据的传输

-- 什么是进程间通信?

        每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程A把数据从用户空间拷到内核缓冲区,进程B再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信。

1、管道的特点

-- 1 先进先出

  • 数据被一个进程读出后,将被从管道中删除,其他读进程将不能再读到这些数据。管道的内容读完后不会保存。

-- 2 单向

  • 数据的流通方向的单向的,一个进程(写进程)在管道的尾部写入数据,另一个进程(读进程)从管道的头部读出数据。

-- 3 管道为空

  • 无法读出数据 会读阻塞(进程试图读空管道时,进程将阻塞)

-- 4 管道为满

  • 写堵塞(管道已经满时,进程再试图向管道写入数据,进程将阻塞。)

  • 管道大小 64KB

alt text

alt text

  • 直接将1024这一块区域写进文件,并没有对该地址的空间做出改变,所以是可以的。

-- 5 管道有两种

  • 无名管道
    -- 没有名字的管道 只能让亲缘(父子)进程使用

  • 有名管道
    -- 在同一个操作系统下 用任意的两个进程都可以使用

-- 6 管道是单向的,一边要么读,一边要么写,不可以又读又写,想要一边读一边写,那就创建2个管道

-- 当进程退出之时,管道也随之释放,与文件保持一致


2、无名管道的使用步骤

(1)在进程中使用 pipe 函数来获取管道的文件描述符

-- 函数头文件

  • #include <unistd.h>

-- 函数的原型

  • int pipe(int pipefd[2]);

-- 函数的作用:

  • 调用该函数可以创建一个无名管道用于父子进程间通信
  • !!!该函数需要在 fork 之前来调用否则会创建两根管道

-- 函数的参数

  • 函数的参数用于返回无名管道的读端口和写端口对应的文件描述符
  • int pipefd[2]:一个 int 类型的数组
  • pipefd[0] 对应读端口
  • pipefd[1] 对应写端口

-- 函数的返回值:

  • 成功返回:0
  • 失败返回:-1
(2)使用 fork 函数来创建子进程
  • pid_t fork(void);
(3)通过获取到的文件描述符来进行数据的传输

-- 因为我们获取的是文件描述符,所以可以直接使用 read 和 write 函数来进行数据的写入和读取

  • ssize_t read(int fd, void *buf, size_t count)
  • ssize_t write(int fd, const void *buf, size_t count)

注:任何的数据传输,接收方接收的数据类型尽量的要跟发送方的一致

alt text

alt text

alt text

(4)当管道不再使用的时候 需要进行关闭

-- 调用 close 函数即可

  • 1 写端口彻底关闭 但是管道中还有数据 读端口可以正常读取 数据读取完毕之后 管道自动关闭
  • 2 读端口彻底关闭 写端口不可以正常写入

alt text

  • 要想彻底关闭管道,需要父子进程都进行 close 操作
    父进程关闭读写端口,子进程关闭读写端口 

    alt text


-- 向管道中写数据,从管道中读数据

alt text

alt text


3、有名管道的使用步骤

-- 因为无名管道使用范围有限(只能在父子进程之间),为了让任意的两个进程都可以使用管道通信,我们就可以用有名管道.

-- 有名管道的特点跟无名管道无区别

(1)创建一个有名管道出来

-- 使用指令创建

alt text

-- 使用函数创建

-- 函数头文件

  • #include <sys/types.h>
  • #include <sys/stat.h>

-- 函数原型

  • int mkfifo(const char *pathname, mode_t mode)

-- 函数的作用:

  • 根据参数来创建一个有名管道文件

-- 函数的参数:

  • pathname:路径和文件名
  • mode:有名管道的文件权限

-- 函数的返回值:

  • 成功返回 0
  • 失败返回 -1

alt text

(2)打开有名管道 (有名管道的使用方式)
  • 使用 open 函数来对有名管道进行打开
  • 有名管道必须要让两个进程同时调用 open 函数才可以打开成功
  • 而且一个进程以只读的方式 一个进程以只写的方式
  • 要想打开有名管道 必须要凑够可读可写这两个权限
(3)通过打开的有名管道进行数据的操作
  • read 和 write 函数来进行数据的写入和读取
  • ssize_t read(int fd, void *buf, size_t count)
  • ssize_t write(int fd, const void *buf, size_t count)
  • 任何的数据传输,接收方接收的数据类型尽量的要跟发送方的一致
(4)关闭有名管道
  • 读端先关闭 写端无法使用
  • 写端先关闭 但是管道中有数据 读端口仍可进行读取

4、删除有名管道函数

-- 函数头文件

  • #include <unistd.h>

-- 函数原型

  • int unlink(const char *pathname)

-- 函数的作用

  • 删除有名管道文件

-- 函数的参数:

  • pathname:填写有名管道文件

-- 函数的返回值:

  • 成功返回 0
  • 失败返回 -1

使用有名管道实现双向通信,用两根管道

alt text

alt text

alt text

-- rr.c

#include "stdio.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include "unistd.h"
int main(int argc,char*argv[])
{
    if(argc<3)
    {
    	printf("格式输入有误!\n");
    	return -1;
    }
    
    
    char buff1[30]={0};
    char buff2[30]={0};
    
    pid_t pid = fork();
    if(pid == 0)
    {
    while(1){
			//sleep(1);
			int fd_r = open(argv[1],O_RDONLY);
			int ret = read(fd_r,buff1,30);
			if(ret>0){
			printf("接收到%d个字节\n",ret);
			printf("buff1:%s\n",buff1);
			}else {
				break;
			}
			memset(buff1,0,30);
			close(fd_r);
		}
    }else if(pid >0){
    while(1){
    		int fd_w = open(argv[2],O_WRONLY);
			scanf("%s",buff2);
			write(fd_w,buff2,strlen(buff2));
			perror("write");
			close(fd_w);
			
    }
    }
    
    
    return 0;
}

-- ww.c

#include "stdio.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "unistd.h"
#include <string.h>

int main(int argc,char*argv[])
{
    if(argc<3)
    {
    	printf("格式输入有误!\n");
    	return -1;
    }
    

    char buff1[30] ={0};
    char buff2[30]={0};
    
    pid_t pid =fork();
    
    if(pid == 0){
    while(1){
    		int fd_w = open(argv[1],O_WRONLY);
			scanf("%s",buff1);
			write(fd_w,buff1,strlen(buff1));
			perror("write");
			close(fd_w);
		}
    }else if(pid > 0){
    	while(1){
    			int fd_r = open(argv[2],O_RDONLY);
				//sleep(2);
				int ret = read(fd_r,buff2,30);
				if(ret>0)
				{
					printf("接收到%d个字节\n",ret);
					printf("buff2:%s\n",buff2);
				}else {
					
					break;
				}
				memset(buff2,0,30);
				close(fd_r);
				
			}
    }
    
 	
    return 0;
}

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

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

相关文章

第八周:机器学习

目录 摘要 Abstract 一、注意力机制V.S.自注意力机制 1、引入 2、注意力机制 3、自注意力机制 二、自注意力机制 1、输入 2、输出 3、序列标注 4、Multi-head Self-attention 5、比较 总结 摘要 前两周学习了CNN的基本架构&#xff0c;针对全局信息的考虑问题&…

【Kotlin设计模式】Kotlin实现单例模式

前言 单例模式&#xff08;Singleton Pattern&#xff09;&#xff0c;是确保一个类只有一个实例&#xff0c;并提供一个全局访问点来访问这个实例。在 Android 中&#xff0c;有许多系统服务和 API 使用了单例模式&#xff0c;比如&#xff1a; Context: 通过getApplication…

SpringBoot2:创建项目及启动时相关报错整理

1、创建时报错 Initialization failed for https://start.aliyun.com/ Please check URL, network and proxy settings.Error message: Error parsing JSON response换官网地址初始化即可&#xff1a;https://start.spring.io/ 那么&#xff0c;大家肯定会疑问&#xff0c;官网…

【SpringBoot】10 日志持久化(log4j2)

介绍 日志概念 日志是系统生成的数据&#xff0c;用于记录网络、端点、物联网、应用程序、操作系统等&#xff0c;在运行时所发生事件的信息&#xff0c;便于开发人员或维护人员进行故障排查、性能优化、安全审计等工作。 日志作用 问题追踪及调试&#xff1a;当程序出现问…

C语言 | Leetcode C语言题解之第372题超级次方

题目&#xff1a; 题解&#xff1a; //计算a的b次方 int mypow(int a, int b){a a % 1337; // 防止a过大超出规模int ret 1;for(int i 0; i < b; i){ret * a;ret ret % 1337; //防止超出规模}return ret; } //整体计算 int superPow(int a, int* b, int bSize){if(a 1…

Android Jitpack制作远程仓库aar流程

开发高效提速系列目录 软件多语言文案脚本自动化方案Android Jitpack制作远程仓库aar流程 Android Jitpack制作远程仓库aar流程 背景aar制作与使用1. aar制作2. aar使用 异常解决总结 博客创建时间&#xff1a;2023.08.24 博客更新时间&#xff1a;2023.08.24 以Android stud…

leetcode刷题之二分算法

目录 简介 第一个错误的版本 算法思路 代码实现 两个数组的交集 算法思路 代码实现 两个数组的交集2 算法思路 代码实现 有效的完全平方数 算法思路 代码实现 猜数字大小 算法思路 代码实现 排列硬币 算法思路 代码实现 寻找比目标字母大的最小字母 代码实…

XTuner微调个人小助手认知实战

1 微调前置基础 本节主要重点是带领大家实现个人小助手微调&#xff0c;如果想了解微调相关的基本概念&#xff0c;可以访问XTuner微调前置基础。 2 准备工作 环境安装&#xff1a;我们想要用简单易上手的微调工具包 XTuner 来对模型进行微调的话&#xff0c;第一步是安装 XTun…

YOLO+Sort实现目标追踪

在前面的目标检测、实例分割的学习中&#xff0c;我们多是对单张图像进行处理&#xff0c;而事实上在我们的实际应用中多数需要对视频进行操作&#xff0c;当然这个操作也是讲视频转换为一帧帧的图像&#xff0c;但博主发现在ultralytics这个算法平台中&#xff0c;针对视频的处…

docker容器基本命令、docker进入容器的指令、容器的备份、镜像底层原理、使用commit命令制造镜像、将镜像推送到阿里云镜像仓库与私服仓库

除了exit 还有 ctrlpq exit退出停止 ctrlpq 退出不停止 将本地镜像推到阿里云 登入阿里云 容器镜像服务 实力列表 镜像仓库 创建镜像仓库 安装里面步骤来 这里192.168.10.145这部分用自己ifconfig地址

虚惊一场的一次事故,在事故中学习

上周日吃着晚饭时&#xff0c;“叮叮”两声&#xff0c;老板在QQ上单独M我。 “服务器好像崩了” “昨天和前天在线人数猛猛下滑 现在更是只有879人在线了” 看完消息&#xff0c;我震惊了&#xff0c;忙用筷子将碗中剩下的饭菜一股脑扒拉到嘴里&#xff0c;来到书桌前坐下&a…

华为OD机试-转盘寿司(C++ Java Python)

题目描述:寿司店周年庆&#xff0c;正在举办优惠活动回馈新老客户。寿司转盘上总共有n盘寿司&#xff0c;prices[i]是第i盘寿司的价格&#xff0c;如果客户选择了第i盘寿司&#xff0c;寿司店免费赠送客户距离第i盘寿司最近的下一盘寿司j&#xff0c;前提是prices[j]<prices…

RISC-V (七)外部设备中断

中断的分类 -本地中断 -software interrupt&#xff08;软终端&#xff09; -timer interrupt&#xff08;定时器中断&#xff09; -全局中断 -external interrupt&#xff08;外部中断 &#xff09; qemu主要是参考FU540-C000这款芯片做出来的&#xff0c;可以经常看一下这款…

学习yolo+Java+opencv简单案例(三)

主要内容&#xff1a;车牌检测识别&#xff08;什么颜色的车牌&#xff0c;车牌号&#xff09; 模型作用&#xff1a;车牌检测&#xff0c;车牌识别 文章的最后附上我的源码地址。 学习还可以参考我前两篇博客&#xff1a; 学习yoloJavaopencv简单案例&#xff08;一&#xff0…

ES5到ES6 js的语法更新

js是一门弱语言类型&#xff0c;为了实现更有逻辑的代码&#xff0c;需要不断更新语法规范&#xff0c;es就是用来规范js语法的标准。 09年发布了es5&#xff0c;到15年发布es6&#xff0c;到现在es6泛指es5.1以后的版本es2016&#xff0c;es2017。 var、let、const 关键字&…

Promise学习之基本方法

前言 上一篇章我们学习了Promise的概念、基本使用、状态等等&#xff0c;对于Promise也有了基础的了解&#xff0c;那本章就对与Promise的方法作基本学习&#xff0c;去了解了解Promise提供了什么方法。 一、then then处理Promise返回结果&#xff0c;接收两个回调函数 第一…

新建一个基于标准新建一个基于标准固件库的工程模板固件库的工程模板(实现LED单灯闪烁)

实验报告原件在资源可选择性下载 一、实验目的&#xff1a; 1.了解STM32固件库&#xff1b; 2.掌握STM32固件库关键子目录及固件库关键文件&#xff1b; 3.能够新建一个基于标准固件库的工程模板并完成编译 二、实验器材&#xff1a; 笔记本或电脑。 三、实验内容&#…

大投资模型 arxiv 量化论文

郭建与沉向阳 摘要 传统的量化投资研究面临着回报递减以及劳动力和时间成本上升的问题。 为了克服这些挑战&#xff0c;我们引入了大型投资模型&#xff08;LIM&#xff09;&#xff0c;这是一种新颖的研究范式&#xff0c;旨在大规模提高绩效和效率。 LIM 采用端到端学习和通…

数据结构系列-归并排序

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 归并排序 递归版本 首先&#xff0c;我们来看一下归并的示意图&#xff1a; 这是归并排序当中分解的过程。 然后便是两个两个进行排序&#xff0c;组合的过程。 归并完美的诠释…

docker镜像,ip,端口映射,持久化

docker 镜像的迁移&#xff1a;导出和导入镜像 查看镜像&#xff1a; [rootdocker ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE centos latest 5d0da3dc9764 2 years ago 231MB 打包 将镜像打包&#xff0c;找到save,可以将…