首页 > 系统相关 >进程间通讯

进程间通讯

时间:2023-04-01 21:46:44浏览次数:45  
标签:通讯 buffer pipefd 管道 进程 close include

一、关于进程间通讯

  • linux下的进程通信手段基本上是从Unix平台上的进程通信手段继承而来的。
  • 每个进程都有自己独立的地址空间,当两个不同进程需要进行交互时,就需要使用进程间通讯
  • 进程间通讯分为单个计算机的进程间通讯与局域网的计算机的进程间通讯
  • 进程间通讯方式有 管道,信号,消息队列,共享内存,网络

二、管道

管道简介

管道分为 无名管道 与 有名管道
无名管道用于父子进程之间通讯
有名管道用于任意进程之间通讯
管道的本质是在内存建立一段缓冲区,由操作系统内核来负责创建与管理,具体通讯模型如下

无名管道

无名管道的特点:

  • 无名管道属于单向通讯
  • 无名管道只能用于 父子进程通讯
  • 无名管道发送端叫做写端,接收端叫做读端
  • 无名管道读端与写端抽象成两个文件进行操作,在无名管道创建成功之后,则会返回读端与写端的文件描述

    创建无名管道需要调用 pipe() 函数
    函数头文件
    #include <unistd.h>
    函数原型
    int pipe(int pipefd[2]);
    函数参数
    pipefd: 用于存储无名管道读端与写端的文件描述符的数组
    pipefd[0]: 读端文件描述符
    pipefd[1]: 写端文件描述符
    函数返回值:
    成功: 0
    失败 : -1,设置 errno
    示例:创建子进程,父进程通过管道向子进程发送"Hello,pipe"
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <wait.h>
#include <stdlib.h>

int main(void){
        pid_t cpid;
        int ret;
        int pipefd[2];

        ret = pipe(pipefd);
        if(ret == -1){
                perror("[ERROR] pipe():");
                exit(EXIT_FAILURE);
        }
        cpid = fork();
        if(cpid == 0){
                ssize_t rbytes;
                char buffer[64] = {0};
                close(pipefd[1]);

                rbytes = read(pipefd[0],buffer,sizeof(buffer));
                if(rbytes == -1){
                        perror("[ERROR] read()");
                        close(pipefd[0]);
                        exit(EXIT_FAILURE);
                }
                printf("buffer: %s\n",buffer);
                close(pipefd[0]);
        }
        else if(cpid > 0){
                ssize_t wbytes;
                char buffer[] = "hello pipe";
                close(pipefd[0]);
                wbytes = write(pipefd[1],buffer,strlen(buffer));
                if(wbytes == -1){
                        perror("[ERROR] write():");
                        wait(NULL);
                        close(pipefd[1]);
                        exit(EXIT_FAILURE);
                }
                close(pipefd[1]);
                wait(NULL);

        }
        return 0;

}

无名管道的特点

  • 当管道为空时,读管道会阻塞读进程
  • 当管道的写端被关闭了,从管道中读取剩余数据后,read 函数返回 0
  • 在写入管道时,确保不超过PIPE BUF字节的操作是原子的
    • 当写入的数据达到PIPE BUF字节时,write()会在必要的时候阻塞直到管道中的可用空间足以原子地完成操作
    • 当写入的数据大于PIPE BUF字节时,write()会尽可能多传输数据以充满这个管道管道的大小是有限的,不能让父 /子进程同时对管道进行读 / 写操作
  • 当一个进程试图想一个管道中写入数据但没有任何进程拥有该管道的打开着的读取描述符,内核向写入进程发送一个SIGPIPE信号

练习

创建一个子进程,负责循环从管道中读取数据,父进程从键盘读取数据后,写入到管道中,输入“quit”字符串时退出

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

int main(void){
        pid_t cpid;
        int ret;
        int pipefd[2];

        ret = pipe(pipefd);
        if(ret == -1){
                perror("[ERROR] pipe():");
                exit(EXIT_FAILURE);
        }
        cpid = fork();
        if(cpid == 0){
                ssize_t rbytes;
                char buffer[64] = {0};
                close(pipefd[1]);
                while(rbytes = read(pipefd[0],buffer,sizeof(buffer))){
                    if(strcmp(buffer,"quit\n") == 0){
                        break;
                    }
                    if(rbytes == -1){
                        perror("[ERROR] read()");
                        close(pipefd[0]);
                        exit(EXIT_FAILURE);
                    }
                    printf("buffer: %s",buffer);
                    memset(buffer,0,64);
                }
                close(pipefd[0]);
        }
        else if(cpid > 0){
                ssize_t wbytes;
                char* buffer = (char*)malloc(100*sizeof(char));
                close(pipefd[0]);
                while(strcmp(buffer,"quit\n") != 0){
                    memset(buffer,0,100);
                    fgets(buffer, 100, stdin);
                    wbytes = write(pipefd[1],buffer,strlen(buffer));
                    if(wbytes == -1){
                        perror("[ERROR] write():");
                        wait(NULL);
                        close(pipefd[1]);
                        exit(EXIT_FAILURE);
                    }
                }
                close(pipefd[1]);
                wait(NULL);
        }
        return 0;

}

标签:通讯,buffer,pipefd,管道,进程,close,include
From: https://www.cnblogs.com/shubin/p/17279455.html

相关文章

  • 计算机网络学习总结(进程之间的通信)
    进程之间通信的方式之一是利用socket最近学习了计算机网络的一些知识,下面是我自己的一些简单理解,可能有些错误的地方(狗头保命)首先长报文在发送的时候是以分组的形式发送的,由应用层发送应用层报文到运输层然后运输层对接收到的每个分组加上一个运输层首部,然后发送到网络层网络......
  • 进程调度算法
    1、先来先服务FCFS非抢占式,按照请求顺序来进行调度。有利于长作业,不利于短作业,短作业等待时间长。2、最短作业优先非抢占式,按照运行时间最短顺序调度。长作业可能饿死,等待短作业一直得不到运行。3、最短剩余时间优先短作业的抢占式版本,按剩余时间调度。4、时间片轮转按FC......
  • 进程的等待
    关于进程等待在子进程运行结束后,进入僵死状态,并释放资源,子进程在内核中的数据结构依然保留.父进程调用wait()与waitpid()函数等待子进程退出后,释放子进程遗留的资源(taskstruct)wait与waitpidwait函数函数头文件#include<sys/types.h>#include<sys/wait.h>函数......
  • C# 当前进程是否有控制台窗口
    WPF应用程序,在VS的项目属性中,可以设置输出类型:那我们在代码中,如何判断应用的类型呢。有没有控制台?是否Windows应用程序还是控制台应用程序?Kernel32下函数GetConsoleWindow可以解决这个问题:[DllImport("kernel32.dll")]privatestaticexternIntPtrGetConsoleWindow();1......
  • Linux系统下进程回收--wait()函数
    进程回收在每个进程退出的时候,内核释放该进程所有资源‘包括打开的文件、占用的内存等。但是仍然会保存一定的信息,这些信息主要是进程控制块PCB的信息(包括进程号、退出状态、运行时间等)。父进程可以调用wait()或waitpid()函数得到它的退出状态,同时彻底清除这个进程。wait()......
  • 进程间的五种通信方式介绍
    进程间通信(IPC,InterProcessCommunication)是指在不同进程之间传播或交换信息。IPC的方式通常有管道(包括无名管道和命名管道)、消息队列、信号量、共享存储、Socket、Streams等。其中Socket和Streams支持不同主机上的两个进程IPC。以Linux中的C语言编程为例。一、管道管道,通常......
  • 进程相关命令
    一、ps命令功能显示当前进程的状态(ProcessStatus)语法ps[options]常用语法选项-A:列出所有的进程-e:与-A功能类似-W:显示加宽可以显示较多的资讯-au:显示较详细的信息-aux:显示所有包含其他使用者的进程示例:ps-aux显示所有进程的详细信息示例:ps-ef......
  • python远程监控linux进程
    1、效果图  2、配置文件  3、源码importparamikoimportioimportcoloramadefprocess(cfg):#创建SSH客户端ssh=paramiko.SSHClient()#自动接受新的主机密钥ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())#连接到......
  • 孤儿进程和僵尸进程简介
    孤儿进程父进程运行结束后,但子进程还在运行(为运行结束),这样的子进程就称为孤儿进程(OrphanProcess)。每当出现一个孤儿进程的时候,内核几把故而进程的父进程设置为init(进程号为1),而init进程会循环地wait()已经退出的子进程。这样,当一个孤儿进程结束了其生命周期的时候,init进程......
  • C#上位机开发源码 上位机项目源代码 采用基于RS485通讯总线的ModbusRtu协议
    C#上位机开发源码上位机项目源代码采用基于RS485通讯总线的ModbusRtu协议,支持用户权限管理、sqlite数据库、实时曲线、历史曲线、历史报表、导出Excel、主界面布局可调带记忆等功能YID:81150611746679046......