首页 > 系统相关 >linux学习记录(十)------进程间的通信(管道通信)

linux学习记录(十)------进程间的通信(管道通信)

时间:2024-08-19 14:25:25浏览次数:13  
标签:return int 通信 ret 管道 fd linux ------ include

文章目录


1.IPC

Inter Process Communication

进程间通信常用的几种方式

1.管道通信:有名管道,无名管道

2.信号- 系统开销小

3.消息队列-内核的链表

4.信号量-计数器

5.共享内存

6.内存映射

7.套接字

2.无名管道

2.1.管道的概念
  • 本质

    • 内核缓冲区
    • 伪文件-不占用磁盘空间
  • 特点:

    • 两部分:
      • 读端,写端,对应两个文件描述符
      • 数据写端流入,读端流出
    • 操作管理的进程被销毁之后,管道自动被释放
    • 管道默认是阻塞的
2.2.管道的原理
  • 内部实现方式:队列
    • 环形队列------>便于数据读取
    • 特点:先进先出
  • 缓冲区大小
    • 默认4K
    • 大小会根据实际情况做适当调整
2.3管道的局限性
  • 队列:
    • 数据只能读取一次,不能重复读取
  • 半双工:
    • 单工:遥控器
    • 半双工:对讲机
      • 数据传输方向是单向的
    • 双工
  • 匿名管道
    • 适用于有血缘关系的进程
2.4.创建匿名管道
int pipe(int fd[2])
fd‐传出参数:
fd[0]‐读端----3
fd[1]‐写端----4
返回值:
0:成功
‐1:创建失败
2.5.父子进程使用管道通信
  • 实现 ps aux| grep “bash”

  • 数据重定向:dup2

2.6.管道的读写行为
  • 读操作

    • 有数据
      • read(fd[1])正常读,返回读的字节数
    • 无数据
      • 写端被全部关闭,read返回0,相当于文件被读到尾部
      • 写端未被全部关闭
        • read被阻塞
  • 写操作

    • 读端被全部关闭
      • 管道破裂,进程被终止(就如同水管一端不停地进水另一端不出水水管迟早被撑爆)
        • 内核给当前进程发送信号SIGPIPE-13,默认处理动作
    • 读端未被全部关闭
      • 缓冲区写满了
        • writezuse
      • 缓冲区未写满
        • write继续写,直到写满为止
  • 如何设置非阻塞?

    • 默认读写两端都阻塞
    • 设置读端为非阻塞pipe(fd)
      • fcntl-变参函数
        • 复制文件描述符-dup
        • 修改文件属性-open的时候对应flag属性
      • 设置方法
//获取原来的flags
int flags = fcntl(fd[0],F+GETFL);
//设置新的flags
flag |=O_NONBLOCK;
fcntl(fd[0],F_SETFL,flags);
fcntl(fd[0],F_SETFL,flags);
2.7.查看管道缓冲区大小
  • 命令

    • ulimit -a
  • fpathconf

父子进程通过管道通信

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
        pid_t pid;
        int fd[2];
        if(pipe(fd))
        {
                printf("create pipe failed\n");
                return -1;
        }
        printf("create pipe successed\n");
        pid = fork();
        if(pid == -1)
        {
                printf("create process failed\n");
                return -2;
        }
        else if(pid > 0)
        {
                close(fd[0]);
                dup2(fd[1],STDOUT_FILENO);//将管道的写端重定义从终端写入
                execlp("ps","ps","aux",NULL);//让父进程执行ps aux 的命令并把数据写到管道
        }
        else if(pid == 0)
        {
                close(fd[1]);
                dup2(fd[0],STDIN_FILENO);//将管道的读出重定义为读到终端
                execlp("grep","grep","bash",NULL);//子进程执行grep bash命令筛选父进程写入的数据并显示到终端
        }

        return 0;
}

3.有名管道

//函数形式:
int mkfifo(const char \*filename,mode_t mode);
/*
*function:创建管道文件
*param:管道文件文件名,权限,创建的文件权限仍然和umask有关系。
*return:创建成功返回0,创建失败返回-1。
*/
3.1.特点
  • 有名管道

  • 在磁盘上有这样一个文件 ls -l ->p

  • 也是一个伪文件,在磁盘大小永久为0

  • 数据存在内核中有一个对应的缓冲区

  • 半双工通信方式

3.2.使用场景

没有血缘关系的进程间通信

3.3.创建方式
  • 命令:mkfifo 管道名

  • 函数:mkfifo

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


int main()
{
        int ret;
        ret = mkfifo("./myfifo",0777);
        if(ret == -1)
        {
                printf("create myfifo failed\n");
                return -1;
        }


        return 0;
}

在这里插入图片描述

3.4.fifo文件可以使用io函数进程操作
  • open/close

  • read/write

  • 不能执行lseek操作

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

int main()
{
	int ret;
	int fd;
	char ReadBuf[50] = {0};
	ret = mkfifo("./myfifo",0777);//创建有名管道
	if(ret == -1)
	{
		printf("make fifo failed\n");
		return -1;
	}

	fd = open("./myfifo",O_RDONLY);//打开有名管道
	if(fd == -1)
	{
		printf("open file failed\n");
		return -1;
	}
	ret = read(fd,ReadBuf,50);//读有名管道的内容
	printf("read %d byte is %s",ret,ReadBuf);

	close(fd);
	return 0;
}

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

int main()
{
	int ret;
	int fd;
	char *str = "hello world";//预定要发送的内容也可以设置从控制终端读
	fd = open("./myfifo",O_WRONLY);
	if(fd == -1)
	{
		printf("open file failed\n");
		return -1;
	}
	ret = write(fd,str,strlen(str));//写数据
	if(ret == -1)
	{
		printf("write error\n");
		return -1;
	}
	close(fd);
	return 0;
}

在这里插入图片描述

标签:return,int,通信,ret,管道,fd,linux,------,include
From: https://blog.csdn.net/qq_63556165/article/details/141276642

相关文章

  • Linux学习记录(九)----进程(四)
    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录8.vfork创建进程9.进程退出1.正常退出2.异常退出上篇:进程(一)中1:进程(二)中2:进程(三)8.vfork创建进程vfork也可以创建进程,与fork有什么区别呢?区别一:vfork可以直接使用父进程存储空间,不拷......
  • 从经济角度来看历史战争,从历史角度来看经济周期
    该文主要通过上世纪二战前的两个历史事件,来聊聊经济的周期萧条和复苏。从经济周期看历史战争,从历史战争看经济周期。这才是一个整个大循环,也就是人们常说的康波周期鉴于多数财经媒体对这个机构的描述太课本化,太简单,存在一些误解,所以该文要结合历史上发生过的事情,把加息......
  • Linux学习记录(十一)———进程间的通信(消息队列)
    文章目录4.消息队列4.1特点4.2.相关函数ftok函数消息队列进程间的通信消息队列全双工通信4.消息队列消息队列,是消息的链表,存放在内核中,一个消息队列由一个标识符(队列ID)来标识。查看消息队列指令ipcs-q4.1特点消息队列是面向记录的,其中的消息具有特......
  • 使用云服务器部署项目----保姆级教程
    1.注册云服务器首先需要一个云服务器2.登录云服务器大家在选择服务器版本的时候尽量选择CentOS7的版本3.注册宝塔Linux面板安装宝塔时选在线安装,输入ip密码就可以自动安装了安装完成后会弹出宝塔访问链接和用户名密码在登录宝塔面板之前,在平台上随便开启一个端口,作为......
  • 该如何面对大量的简历筛选和繁琐的面试流程???
    在当今这个人才竞争激烈的时代,招聘工作变得越来越复杂和具有挑战性。HR在招聘过程中需要从成百上千的简历中筛选出符合岗位要求的候选人,然后面试官通过面试进一步评估他们的技能和文化适应性。过程不仅耗时而且效率低下,尤其是对于大型企业而言,面对海量的简历和面试,如何快速而准......
  • JAVA常用API
     目录1.Math1.1Math类概述1.2Math中方法的调用方式1.3Math类的常用方法2.System 2.1System类的常用方法2.2示例代码3.Object类的toString方法3.1Object类概述3.2查看源代码的方式3.3重写toString方法的方式3.4toString方法的作用4.Object类的equals方......
  • 不会吧不会吧,身为HR的你还不知道智能招聘???
    身为HR的你是否遇到这样的困惑,每天面对大量的简历等着你去筛选,选出基本符合岗位需求的然后再邀请到线下面试,流程重复且工作量大,还不一定能找到符合所要的条件,这时候我们可以适当借助已有的智能工具,来辅助我们,帮助我们提高招聘的效率以及减少招聘的成本。那么在AI发展迅速的时......
  • 在繁忙的编码生活中寻找平衡:高效工作与持续学习的艺术
    目录前言1.高效编码实践:提升工作效率的关键1.1代码复用与模块化设计1.2持续集成与自动化测试2.时间管理技巧:合理规划工作与学习时间2.1番茄工作法与专注力管理2.2时间块规划:分配专属的学习时间3.学习路径选择:广泛涉猎还是专注深入3.1广泛涉猎:适应多变的技术环......
  • 洛谷 P5461 赦免战俘
    赦免战俘题目背景借助反作弊系统,一些在月赛有抄袭作弊行为的选手被抓出来了!题目描述现有2n×2......
  • 常见面试题问题及答案
    常见面试题问题及答案1、什么是API端点(APIendpoint)?说说相关技术点用于访问特定资源或功能的网络地址或URI,代表了API的一个具体操作或服务,并定义了客户端与服务器之间进行交互的方式;1:URI(统一资源标识符),包含了协议(如HTTP/HTTPS)、主机名、路径、查询参数等2:请求方法,GET(获......