首页 > 系统相关 >操作系统进程-进程间通信的概述、匿名管道pipe和有名管道mkfifo函数的介绍及应用

操作系统进程-进程间通信的概述、匿名管道pipe和有名管道mkfifo函数的介绍及应用

时间:2025-01-18 15:30:03浏览次数:3  
标签:int FIFO 间通信 管道 fd 进程 buf

进程间通信(IPC)

概述

进程间通信(Inter Process Communication)是指在两个或多个不同的进程间传递或者交换信息。

进程是一个独立的资源管理单元,不同的进程之间资源是独立的,不能在一个进程中直接访问另一个进程的资源,但是进程间不是孤立的,也需要一些信息的交互和状态传递,所以就需要进程间数据传递,同步和异步的机制

进程间通讯的目的
  • 数据传输:一个进程需要将它的数据发送给另一个进程
  • 共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到
  • 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种时间(如进程终止时要通知父进程)
  • 资源共享的同步:多个进程之间共享同样的资源。为了作到这一点,需要内核提供锁和同步机制
  • 进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。
linux进程间通信方式:
  • 管道:无名管道(pipe)和有名管道(FIFO)
  • 消息队列
  • 共享内存
  • 信号量
  • 信号(signal)
  • 套接字(socket)

匿名管道与有名管道

匿名管道
概述

​ 无名管道,是一种具有两个端点的通信通道,管道的一端用于读取管道内数据,另一端用于将数据写入到管道内。创建一个管道后,会获取一对文件描述符,用于读写。匿名管道通常用在父子进程之间,由父进程创建匿名管道,子进程会继承管道的读端和写端,实现通讯。

​ 管道是单向的、先进先出、无结构的字节流。写进程在管道的尾端写入数据,读进程在管道的首端读出数据。数据读出后将从管道中移走,其他读进程都不能再读到这些数据。管道提供了简单的流控制机制。进程试图读空管道时,在有数据写入管道前,进程将一直阻塞。同样,管道已经满时,进程再试图写管道,在其他进程从管道中移走数据之前,写进程将一直阻塞。

  • 由于pipe存在于内存中,并且只有创建它的进程可以直接拿到读写两个文件描述符,其他的进程想要获取到这两个描述符相对困难,通常做法是父进程先创建无名管道,再创建子进程。由于子进程继承父进程打开的文件描述符,所以父子进程就可以通过无名管道进行通信。
  • 无名管道是临时的,在通讯完成进程退出后,将自动消失,对管道的读写可以使用read和write函数
  • 无名管道默认情况下只有64kb
pipe

调用头文件

#include <unistd.h>

函数原型

int pipe(int fd[2]);

功能

创建一个匿名管道

参数

  • fd[2]:管道的两个文件描述符

    管道创建后,可以直接操作这两个文件描述符

    fd[0]:读端

    fd[1]:写端

返回值

成功返回0,失败返回**-1**,提供错误码,可使用perror

无名管道示例:

//父子进程通信
#include "head.h"

int main(int argc, char const *argv[])
{
    //建立2个无名管道(一个用来主进程发,一个用来子进程发)
    int fds1[2] = {0};
    int fds2[2] = {0};
    int r1 = pipe(fds1);
    int r2 = pipe(fds2);
    if (r1 == -1 || r2 == -1)
    {
        perror("pipe failed");
        return -1;
    }
    
    //创建子进程
    pid_t pid = fork();

    if (pid == 0)
    {
        char data[100] = {0};
        read(fds1[0],data,sizeof(data));
        printf("Child receive:%s\n",data);

        char *msg = "Child send";
        write(fds2[1],msg,strlen(msg));
    }
    else if (pid > 0)
    {
        char *msg = "Parent send";
        write(fds1[1],msg,strlen(msg));

        char data[100] = {0};
        read(fds2[0],data,sizeof(data));
        printf("Parent receive:%s\n",data);
    }
    else
    {
        perror("fork failed");
        return -1;
    }
    
    return 0;
}
有名管道
概述

​ 有名管道,有名管道可以用于不相关的进程之间的通信。

​ 创建有名管道的进程可以给管道取名字以及路径,该路径名是以特殊的文件存放在文件系统中,因此两个进程可以通过访问该路径来建立练习,进行进程间的数据交换,有名管道和无名管道都遵循先进先出的原则。

​ 有名管道是一个特殊的文件,它和普通文件一样具有磁盘存放路径,文件权限和其他属性,但两者又有区别,有名管道并不会在磁盘中存放真正的信息,信息存放在内存中。通信的两个进程结束后,信息会自动消失,但管道文件路径依然存在。

有名管道的特点

  1. 如果以的方式打开有名管道,其他进程需要以的方式打开,否则进程会阻塞;如果以的方式打开,而没有进程,读进程会阻塞,反之亦然。如果一个进程以读写的方式打开,此进程充当了读写两个身份,则进程不会阻塞。
  2. 如果两个进程分别以读写的方式打开有名管道,其中一个进程中途退出:
  3. 如果退出的是读操作,则写操作返回SIGPIPE信号;
  4. 如果退出的是写操作,测读操作将不再阻塞,直接返回0。
mkfifo

调用头文件

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

函数原型

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

功能

创建一个命名管道(文件)

参数

  • pathname:想要建立的FIFO文件路劲和文件名
  • mode:FIFO文件权限

返回值

成功,返回0,失败返回**-1**,提供错误码,可以使用perror

有名管道示例(两个进程通信):

#include "head.h"

#define FIFO_PATH "/tmp/temp_fifo"
int main(int argc, char const *argv[])
{
    //判断文件存不存在,如果不存在,则新建
    if (access(FIFO_PATH, F_OK) == -1)
    {
        int r1 = mkfifo(FIFO_PATH, 0777);
        if (r1 == -1)
        {
            perror("mkfifo failed");
            return -1;
        }
    }
    //打开文件
    int fd = open(FIFO_PATH, O_WRONLY);
    if (fd == -1)
    {
        perror("open failed");
        return -1;
    }
    while (1)
    {
        char buf[64] = {0};
        //从键盘输入数据
        fgets(buf, 64, stdin);
        //将读到的换行符删掉(换成字符串结束标志)
        buf[strcspn(buf, "\n")] = '\0';
        //写入文件
        write(fd, buf, strlen(buf));
        //如果写入的是bye,则退出
        if (strcmp(buf, "bye") == 0)
        {
            exit(0);
        }
        memset(buf, 0, sizeof(buf));
    }

    return 0;
}

#include "head.h"

#define FIFO_PATH "/tmp/temp_fifo"
int main(int argc, char const *argv[])
{
    //判断文件存不存在,若不存在,则创建
    if (access(FIFO_PATH, F_OK) == -1)
    {
        int r1 = mkfifo(FIFO_PATH, 0777);
        if (r1 == -1)
        {
            perror("mkfifo failed");
            return -1;
        }
    }
    //读方式打开文件
    int fd = open(FIFO_PATH, O_RDONLY);
    if (fd == -1)
    {
        perror("open failed");
        return -1;
    }

    while (1)
    {
        char buf[64] = {0};
        //读数据
        read(fd, buf, sizeof(buf));
        //判断接收到的是不是bye,如果是,则退出
        if (strcmp(buf, "bye") == 0)
        {
            exit(0);
        }
        //不是,则打印字符串
        printf("receive:%s\n", buf);
        memset(buf, 0, sizeof(buf));
    }

    return 0;
}

标签:int,FIFO,间通信,管道,fd,进程,buf
From: https://blog.csdn.net/Are_pro_bald/article/details/145228040

相关文章

  • 系统编程(进程通信--消息队列)
    消息队列概念:消息队列就是一个消息的链表,提供了一种由一个进程向另一个进程发送块数据的方法。另外,每一个数据块被看作有一个类型,而接收进程可以独立接收具有不同类型的数据块,在许多方面看来,消息队列类似于有名管道,但是却没有与打开与关闭管道的复杂关联。优点:1.通过发......
  • 系统编程(进程通信--信号进阶)
    常见问题解决vscode远程连接虚拟机上ubuntu系统,在编写代码时用到的Linux系统函数或者某些常量不提醒或者报红色波浪线的问题:信号的屏蔽和解除信号的屏蔽和解除屏蔽函数的基本使用:#include<stdio.h>#include"header.h"voidhandler(intsignum){pri......
  • 系统编程(进程通信--综合练习)
    实现两个没有亲缘关系的进程之间通过共享内存实现一个小文件(小于10K)的数据拷贝。(可申请文件大小的共享内存,一次性写入文件所有内容,读取共享内存的进程访问数据后,进行文件存储)思路要实现两个进程之间通过共享内存进行文件拷贝,可以按照以下步骤进行:创建共享内存:进程A创......
  • Linux进程概念-进程状态
    在上一篇已经了解了在进程中的基本概念,现在我来了解一下进程的相关状态;对于进程的状态,在详细了解之前我们可以来一个粗略的理解:进程的状态可以理解为就是一个整数,用宏定义实现R,S等状态;也就是进程状态就是take_struck内的一个整数;如果不理解也没关系,下面来看看对进程状......
  • 【Docker】Supervisor 实现单容器运行多服务进程
    本文内容均来自个人笔记并重新梳理,如有错误欢迎指正!如果对您有帮助,烦请点赞、关注、转发、订阅专栏!专栏订阅入口| 精选文章 | Kubernetes |Docker|Linux |羊毛资源 | 工具推荐 |往期精彩文章【Docker】(全网首发)KylinV10下MySQL容器内存占用异常的解决......
  • 进程与线程有什么区别?JS的单线程带来哪些好处?
    进程与线程的区别:资源拥有与管理:进程是操作系统资源分配的基本单位,它拥有独立的代码和数据空间(程序上下文),以及独立的内存、I/O、CPU等资源。而线程是处理器任务调度和执行的基本单位,它共享进程的资源,包括地址空间和内存等。因此,进程间的资源是独立的,而同一进程的线程间资源是共......
  • Java 大数据自动化数据管道构建:工具与最佳实践(47)
           ......
  • Java多进程多线程处理详解
    在Java编程中,多进程和多线程是两种常见的并发编程技术,用于提高程序的执行效率和响应速度。本文将详细介绍Java中的多进程和多线程处理,包括理论概述和代码示例。通过本文,你将了解如何在Java中实现多进程和多线程,以及它们在实际应用中的价值和意义。一、理论概述1.多进程与多线程......
  • 【Linux】信号的艺术:深入理解 Linux 进程信号
    ......
  • 浅谈Java之进程锁
    一、基本介绍在Java中,进程锁通常是指在多进程环境下,用于协调不同进程对共享资源访问的锁机制。由于Java本身主要是面向多线程编程设计的,它没有内置的进程锁概念。不过,我们可以通过一些外部机制或者特定的库来实现进程锁。二、关键点一、死锁预防定义死锁是指两个或多......