【Linux】进程通信----管道通信(下)

简介: 【Linux】进程通信----管道通信(下)

【Linux】进程通信----管道通信(上)    https://developer.aliyun.com/article/1565747



3.管道特征

1.管道的生命周期随进程,进程退出,管道释放

2.管道可以用来进行具有血缘关系的进程间通信(常用于父子通信)

3.管道是面向字节流的

4.半双工—单向通信(特殊)

5.互斥与同步机制——对共享资源进行保护的方案


💫 命名管道

概念:

我们前面已经知道:匿名管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。那如果两个毫不相干的进程间通信交互呢?如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。命名管道是一种特殊类型的文件


1.mkfifo

使用说明

NAME
       mkfifo - make FIFOs (named pipes)
 
SYNOPSIS
    #include <sys/types.h>
    #include <sys/stat.h>
    int mkfifo(const char *pathname, mode_t mode);
RETURN VALUE
       On success mkfifo() returns 0.  In the case of an error, -1 is returned (in which case, errno is set appropriately).


在当前路径下直接创建命名管道:

mkfifo named_pipe

往管道文件写东西:



2.创建管道文件

分为三个文件:comm.hpp:公共文件(同一份资源),server.cc:读取端,clinet.cc:写入端

comm.hpp文件(同一份资源)

#pragma once
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <string>
#include <cerrno>
#include <cstring>
#include <cassert>
 
#define NAMED_PIPE "/tmp/mypipe.name"
 
bool createFifo(const std::string &path)
{
    umask(0);
    int n = mkfifo(path.c_str(),0666);
    if(n==0) return true;
    else
    {
        std::cout<<"errno:"<<errno<<"err string:"<<strerror(errno)<<std::endl;
        return false;
    }
}


server.cc:

#include "comm.hpp"
int main()
{
    bool ret = createFifo(NAMED_PIPE);
    assert(ret);
    (void)ret;
    return 0;
}

运行:



3.删除管道文件

使用说明

unlink   注意头文件,函数的参数以及返回值这三个主要部分:

NAME
       unlink - remove a directory entry
 
SYNOPSIS
       #include <unistd.h>
 
       int unlink(const char *path);
RETURN VALUE
       Upon successful completion, 0 shall be returned. Otherwise, -1 shall be returned and errno set to indicate the error. If -1 is returned, the named file shall not be changed.
 


在comm.hpp中封装好删除的函数:

void removeFifo(const std::string &path)
{
    int n = unlink(path.c_str());
    assert(n==0);
    (void)n;//防止n没使用而警告
}


在server.cc中进行调用:

#include "comm.hpp"
 
int main()
{
    bool ret = createFifo(NAMED_PIPE);
    assert(ret);
    (void)ret;
 
    removeFifo(NAMED_PIPE);
    return 0;
}


至此,创建和删除管道文件的操作我们实现完毕。下面进入通信环节

4.通信

说明:

其实在了解完了匿名管道之后,对于命名管道我们能够更好的理解:

client.cc(写端):

#include "comm.hpp"
 
int main()
{
    int wfd = open(NAMED_PIPE,O_WRONLY);
    if(wfd<0) exit(1);
    //write
    char buffer[1024];
    while(true)
    {
        std::cout<<"Please Say:";
        fgets(buffer,sizeof(buffer),stdin);
        //if(strlen(buffer)>0) buffer[strlen(buffer)-1] = 0;
        ssize_t n = write(wfd,buffer,strlen(buffer));
        assert(n==strlen(buffer));
        (void)n;
    }
    close(wfd);
    return 0;
}


server.cc(读端):

#include "comm.hpp"
 
int main()
{
    bool ret = createFifo(NAMED_PIPE);
    assert(ret);
    (void)ret;
 
    int  rfd = open(NAMED_PIPE,O_RDONLY);
    if(rfd<0) exit(1);
 
    //read
    char buffer[1024];
    while(true)
    {
        ssize_t s = read(rfd,buffer,sizeof(buffer)-1);
        if(s>0)
        {
            buffer[s] = 0;
            std::cout<<"client->server" <<buffer<<std::endl;
        }
        else if(s==0)
        {
            std::cout<<"client quit,俺也一样"<<std::endl;
            break;
        }
        else
        {
            std::cout<<"err string:"<<strerror(errno)<<std::endl;
            break;
        }
    }
    close(rfd);
    removeFifo(NAMED_PIPE);
    return 0;
}


进行通信:



读端多出一行空行:写端输入之后多按了回车,修改为buffer[strlen(buffer)-1] = 0;

if(strlen(buffer) > 0) buffer[strlen(buffer) - 1] = 0;



🌙 管道通信的优化

管道通信的优点有以下几点:

  • 管道通信是简单易用的,只需要使用系统调用 pipe 或 mkfifo 就可以创建一个管道文件,然后使用文件操作函数来读写数据。
  • 管道通信是安全的,匿名管道只能用于具有亲缘关系的进程间通信,命名管道可以通过文件权限来控制访问。
  • 管道通信是面向字节流的,不需要事先约定数据的格式,也不需要考虑字节序的问题。


管道通信的缺点有以下几点:


  • 管道通信是单向的,如果要实现双向通信,需要创建两个管道。
  • 管道通信是阻塞式的,如果读端没有数据可读或者写端没有空间可写,进程会被阻塞。
  • 管道通信是缓冲区有限的,如果写入数据过多而读出数据过少,会导致缓冲区满而无法继续写入。
  • 管道通信是不可靠的,如果读端或者写端被关闭,另一端可能会收到错误的信号或者返回值。


改进管道通信性能和效率的方法有以下几点:


  • 使用双向管道,可以实现两个进程之间的双向通信,而不需要创建两个单向管道。双向管道可以通过 socketpair 系统调用来创建,返回两个文件描述符,分别表示管道的两端。
  • 使用非阻塞模式,可以避免进程在读写管道时被阻塞,提高并发性能。非阻塞模式可以通过 fcntl 系统调用来设置文件描述符的 O_NONBLOCK 标志。
  • 使用自定义协议,可以根据通信的需求和场景,设计合适的数据格式和交互方式,提高数据传输的效率和可靠性。自定义协议可以包括数据包的长度、类型、校验码等信息。
  • 调整管道缓冲区的大小,可以根据数据量的大小和频率,选择合适的缓冲区大小,避免缓冲区溢出或者空闲浪费。管道缓冲区的大小可以通过 fcntl 系统调用来设置 F_SETPIPE_SZ 标志,并且可以通过 /proc/sys/fs/pipe-max-size 来修改最大容量。


🌟结束语 

      今天内容就到这里啦,时间过得很快,大家沉下心来好好学习,会有一定的收获的,大家多多坚持,嘻嘻,成功路上注定孤独,因为坚持的人不多。那请大家举起自己的小手给博主一键三连,有你们的支持是我最大的动力💞💞💞,回见。


目录
相关文章
|
8月前
|
并行计算 Linux
Linux内核中的线程和进程实现详解
了解进程和线程如何工作,可以帮助我们更好地编写程序,充分利用多核CPU,实现并行计算,提高系统的响应速度和计算效能。记住,适当平衡进程和线程的使用,既要拥有独立空间的'兄弟',也需要在'家庭'中分享和并行的成员。对于这个世界,现在,你应该有一个全新的认识。
312 67
|
7月前
|
Web App开发 Linux 程序员
获取和理解Linux进程以及其PID的基础知识。
总的来说,理解Linux进程及其PID需要我们明白,进程就如同汽车,负责执行任务,而PID则是独特的车牌号,为我们提供了管理的便利。知道这个,我们就可以更好地理解和操作Linux系统,甚至通过对进程的有效管理,让系统运行得更加顺畅。
231 16
|
7月前
|
Unix Linux
对于Linux的进程概念以及进程状态的理解和解析
现在,我们已经了解了Linux进程的基础知识和进程状态的理解了。这就像我们理解了城市中行人的行走和行为模式!希望这个形象的例子能帮助我们更好地理解这个重要的概念,并在实际应用中发挥作用。
149 20
|
6月前
|
监控 Shell Linux
Linux进程控制(详细讲解)
进程等待是系统通过调用特定的接口(如waitwaitpid)来实现的。来进行对子进程状态检测与回收的功能。
140 0
|
6月前
|
存储 负载均衡 算法
Linux2.6内核进程调度队列
本篇文章是Linux进程系列中的最后一篇文章,本来是想放在上一篇文章的结尾的,但是想了想还是单独写一篇文章吧,虽然说这部分内容是比较难的,所有一般来说是简单的提及带过的,但是为了让大家对进程有更深的理解与认识,还是看了一些别人的文章,然后学习了学习,然后对此做了总结,尽可能详细的介绍明白。最后推荐一篇文章Linux的进程优先级 NI 和 PR - 简书。
211 0
|
6月前
|
存储 Linux Shell
Linux进程概念-详细版(二)
在Linux进程概念-详细版(一)中我们解释了什么是进程,以及进程的各种状态,已经对进程有了一定的认识,那么这篇文章将会继续补全上篇文章剩余没有说到的,进程优先级,环境变量,程序地址空间,进程地址空间,以及调度队列。
137 0
|
6月前
|
Linux 调度 C语言
Linux进程概念-详细版(一)
子进程与父进程代码共享,其子进程直接用父进程的代码,其自己本身无代码,所以子进程无法改动代码,平时所说的修改是修改的数据。为什么要创建子进程:为了让其父子进程执行不同的代码块。子进程的数据相对于父进程是会进行写时拷贝(COW)。
189 0
|
3月前
|
Linux 应用服务中间件 Shell
二、Linux文本处理与文件操作核心命令
熟悉了Linux的基本“行走”后,就该拿起真正的“工具”干活了。用grep这个“放大镜”在文件里搜索内容,用find这个“探测器”在系统中寻找文件,再用tar把东西打包带走。最关键的是要学会使用管道符|,它像一条流水线,能把这些命令串联起来,让简单工具组合出强大的功能,比如 ps -ef | grep 'nginx' 就能快速找出nginx进程。
485 1
二、Linux文本处理与文件操作核心命令
|
3月前
|
Linux
linux命令—stat
`stat` 是 Linux 系统中用于查看文件或文件系统详细状态信息的命令。相比 `ls -l`,它提供更全面的信息,包括文件大小、权限、所有者、时间戳(最后访问、修改、状态变更时间)、inode 号、设备信息等。其常用选项包括 `-f` 查看文件系统状态、`-t` 以简洁格式输出、`-L` 跟踪符号链接,以及 `-c` 或 `--format` 自定义输出格式。通过这些选项,用户可以灵活获取所需信息,适用于系统调试、权限检查、磁盘管理等场景。
329 137
|
3月前
|
安全 Ubuntu Unix
一、初识 Linux 与基本命令
玩转Linux命令行,就像探索一座新城市。首先要熟悉它的“地图”,也就是/根目录下/etc(放配置)、/home(住家)这些核心区域。然后掌握几个“生存口令”:用ls看周围,cd去别处,mkdir建新房,cp/mv搬东西,再用cat或tail看文件内容。最后,别忘了随时按Tab键,它能帮你自动补全命令和路径,是提高效率的第一神器。
771 57