【Linux】进程通信

目录

一、管道通信

二、共享内存

三、消息队列


一、管道通信

管道是由操作系统维护的一个文件,管道通信的本质就是将管道文件作为临界资源,实现不同进程之间的数据读写,但是管道只允许父子进程或者兄弟进程之间的通信。

管道文件本身是全双工机制的,但是在管道通信中,它的工作模式是半双工的,在管道通信之前,读端会关闭对管道文件的写通道,写端会关闭对管道文件的读通道。

当读端在读数据时,若写端关闭,读端会将管道文件中剩余数据读取结束之后再关闭;当写端在写数据时,若读端关闭,写端会被操作系统直接关闭。

那么管道通道如何实现数据交互呢?方法是创建两个管道进行通信。

管道通信方式分为匿名管道命名管道,由 pipe() 系统调用创建并打开,命名管道由 mkfifo() 系统调用创建并由 open() 打开,他们的通信本质是一样的。

// comm.hpp 头文件
#pragma once
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <string>
#include <cstring>
#include <cerrno>
#include <cassert>
#include <unistd.h>
#include <fcntl.h>
#include <fstream>

#define NAMED_PIPE "./named_pipe"

bool create_fifo(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; 
    }
}

void remove_fifo(const std::string& path) {
    int n = unlink(path.c_str());
    // unlink 函数功能是删除文件,但会在判断此文件状态之后再删除
    // 若有进程打开此文件,则不会立即删除,等到无进程打开该文件时才会删除
    // 若此文件有多个链接,则进行连接数减一操作
    // 执行成功返回 0,失败返回 -1
    assert(n == 0);
}
// Server
#include "comm.hpp"

int main() {
    std::cout << "server begin" << std::endl;
    int rfd = open(NAMED_PIPE, O_RDONLY);
    if (rfd < 0) {
        bool r = create_fifo(NAMED_PIPE);
        assert(r);
        rfd = open(NAMED_PIPE, O_RDONLY);
    }

    // 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, me too" << std::endl;
            break;
        }
        else {
            std::cout << "err string: " << strerror(errno) << std::endl;
            break;
        }
    }

    close(rfd);
    std::cout << "server end" << std::endl;

    remove_fifo(NAMED_PIPE);
    return 0;
}
// Client
#include "comm.hpp"

int main() {
    std::cout << "client begin" << std::endl;
    int wfd = open(NAMED_PIPE, O_WRONLY, 0666);
    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(buffe
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AllinTome

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值