05进程间通信-学习笔记

进程间通信(IPC)

概念

进程信技术简称IPC,可以利用此技木让多个进程相传建消数据,有大量的进程间通信方案

  • pipe 匿名管道
  • fifo 命名管简单理解,管道文件是一个指向内核管道缓冲区的指针,所有向管道文件读写的操作,都会重定向到内核管道中道
  • Posix 消息队列
  • System 消息队列
  • Signal 信号
  • Socket 套接字
  • MMAP 文件映射

进程有虚拟地址空间,进程间通信在虚拟地址的哪一层实现的?

绝大多数进程间通信是在内核层完成的, 因为内核层内存共享

pipe 匿名管道

为了便于开发者使用管道可以使用pipe函数创建管道,创建成功后会生成两个文件描述符,分别指向管道的读端fds[0]和写端fds[1]。匿名管道只能再有亲缘关系的进程之间使用

管道的原理

两个进程公用一个管道,实现通信

管道的特点
  1. 是一种传输介质,可以传输数据
  2. 管道传输具有方向性
  3. 管道具备存储能力,虽然不能持久存储,只能暂存
缺点

匿名管道只能在有亲缘关系的进程间的通信

使用管道

创建
C 复制代码
pipe(int fds[2]);

注意:管道创建要在 创建子进程之前完成, 避免子进程创建管道

使用
C 复制代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <pthread.h>
#include <signal.h>

#define MSG "HI"

int main()
{
    pid_t pid;
    int fds[2];

    pipe(fds);
    pid = fork();
    // 父进程写,子进程读
    if (pid > 0)
    {

        close(fds[0]); // 父进程关闭读功能,文件描述符-1
        printf("parent pid %d alive..\n", getpid());
        sleep(5);
        write(fds[1], MSG, strlen(MSG)); // 父进程写入信息
        printf("parent pid %d send msg success..\n", getpid());
        close(fds[1]); // 父进程使用完成写的功能,关闭写功能,文件描述符-1
    }
    else if (pid == 0)
    {
        close(fds[1]); // 子进程关闭写功能,文件描述符-1
        char buffer[1024];
        bzero(buffer, sizeof(buffer));
        read(fds[0], buffer, sizeof(buffer)); // 子进程读管道中的内容

        printf("child read msg %s \n", buffer);
        close(fds[0]); // 子进程使用完成读的功能,关闭写功能,文件描述符-
        exit(0);
    }
    else
    {
        perror("FORK CALL FAILED");
        exit(0);
    }
}
回收
  1. 每个指向管道的描述符都是一个引用计数,如果引用计数为0,系统自动释放管道空间,否则管道一直存在于内核层
  2. 管道使用时要确定通信方向,父写子读,子写父读,父子进程将不用的描述符关闭 关闭不用的
  3. pipe_fd使用完毕要close 引用计数-1 用完要关闭
  4. shutdown可以直接将引用计数清0

工作方式

单工 : 确定通信方向, 非读即写, 不可变更
半双工/可调节单工: 非读即写,但是不同时刻可以调节读写
双工:可以同时读写

匿名管道使用时的四种特殊情况

这四种情况具有普遍意义

  1. 管道的读写两端存在但是写端未向管道内写数据,读端读取完管道数据后如果管道为null,再次读阻塞
  2. 管道读写两端存在,但是读端未读取管道数据,写端写满管道后,再次写阻塞
  3. 管道写端关闭,读端读取管道剩余内容后,再次读读到0
  4. 管道读端关闭,写端向管道写数据,系统会发送SIGPIPE信号,杀死写端进程,读端关闭的情况下不允许写端访问管道

在一个C/S模型中,客户端发送了一条请求消息之后客户端异常关闭,服务端回复结果时异常关闭,服务端异常关闭原因?

(SIGPIPE信号)send(sockfd , buffer, size , MSG NOSIGNAL)

FIFO 命名管道

是一个内核缓冲区,为环形队列结构, 大小为4k,命名管道可以解决无关联进程间的通信

特点

管道通信与传统的文件传输不同,读取文件内容并不会除文件内容,但是管道是队列结构,出队的数据会从管道消失

可以持久化存储的磁盘文件并不适合作为传输介质

原理

简单理解,管道文件是一个指向内核管道缓冲区的指针,所有向管道文件读写的操作,都会重定向到内核管道中

使用

bash 复制代码
mkfifo pname #命令创建管道文件

mkfifo(char * pname,0664) #函数创建管道文件

管道文件的访问是要凑齐两种权限的 即使 RDWR,如果某个进程以一种权限打开管道文件, open函数会立即阻塞,等待另一种权限。即使只有一个进程 只要满足读写权限,就可以成功打开管道了

命名管道的两种特殊情况

一个读端中存在多个读序列,阻塞读只对第一个读序列有效,其他读序列被设置为非阻塞

管道的原子访问与非原子访问

判定是原子传输或是非原子,取决于用户发送数据包大小,如果数据包<=管道大小, 则是原子传输,如果数据包>管道大小(即4K) 就是非原子传输

非原子访问,最大化的利用容器空间, 只有容器满时才会限制写端,读写效率传输效率高,但是数据会被多次拆分,会对读端造成一些麻烦,读端要验证数据包完整性后才可以使用

mmap文件映射

功能

是一种内存映射文件的技术,它允许将文件映射到进程的虚拟内存空间,使得文件的内容可以像访问内存一样被读取和写入。

1、基本使用

头文件

c 复制代码
#include <sys/mman.h>

函数原型、参数、返回值

c 复制代码
void * ptr = mmap(NULL , size , PROT READIPROT WRITE , int how , int fd , 0);

参数

映射方式

共享映射 MAP_SHARED,共享映射有 Sync同步机制

私有映射 MAP_PRIVATE

原理

多进程间利用 MAP_SHARED的Sync同步机制可以实现共享映射实现进程通信

返回值

成功返回映射内存地址ptr

失败返回MAP_FAILED关键字

回收

c 复制代码
munmap(ptr,size); //释放映射内存

使用细节

  1. 确定消息结构体大小
  2. 根据消息结构体大小,确定映射文件大小。大小为消息结构体的倍数
  3. 拓展空文件,使用截断方式 ,将映射文件拓展成一个指定的大小ftruncate(fd,sizeof(msg_t)*4096)
c 复制代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <sys/mman.h>

int main()
{
    int fd;
    fd = open("map_file", O_RDWR);
    int size = lseek(fd, 0, SEEK_END);
    int *ptr = NULL;
    if ((ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED)
    {
        perror("mmap call failed");
        exit(0);
    }
    close(fd);
    sleep(10);
    ptr[0] = 0x34333231;
    munmap(ptr, size);
    return 0;
}

2、大数据文件处理,切割处理

最后一个参数,控制偏移量

映射偏移量必须是4k的整数倍,因为内存分页一页为4k。

3、零拷贝,减少拷贝开销

零拷贝并不是指完全节省拷贝或切换开销,而是尽可能较少

相关推荐
longze_72 小时前
Ubuntu连接不上网络问题(Network is unreachable)
linux·服务器·ubuntu
Dirschs2 小时前
【Ubuntu22.04安装ROS Noetic】
linux·ubuntu·ros
qianshanxue112 小时前
ubuntu 操作记录
linux
AmosTian5 小时前
【系统与工具】Linux——Linux简介、安装、简单使用
linux·运维·服务器
这我可不懂8 小时前
Python 项目快速部署到 Linux 服务器基础教程
linux·服务器·python
车车不吃香菇8 小时前
java idea 本地debug linux服务
java·linux·intellij-idea
tan77º8 小时前
【Linux网络编程】Socket - TCP
linux·网络·c++·tcp/ip
kfepiza9 小时前
Linux的`if test`和`if [ ]中括号`的取反语法比较 笔记250709
linux·服务器·笔记·bash
CodeWithMe9 小时前
【Note】《深入理解Linux内核》 第十九章:深入理解 Linux 进程通信机制
linux·运维·php
vvw&11 小时前
Linux 中的 .bashrc 是什么?配置详解
linux·运维·服务器·chrome·后端·ubuntu·centos