Linux | 进程间通信:管道、消息队列、共享内存与信号量

news/2024/9/18 20:37:45 标签: linux, 进程通信

文章目录

  • 《深入理解进程间通信:管道、消息队列、共享内存与信号量》
    • 一、进程间通信介绍
      • (一)进程间通信目的
      • (二)进程间通信发展
      • (三)进程间通信分类
    • 二、管道
      • (一)什么是管道
      • (二)匿名管道
      • (三)管道特点
      • (四)命名管道
    • 三、共享内存
      • (一)共享内存简介
      • (二)共享内存数据结构
      • (三)共享内存函数
    • 四、消息队列
    • 五、信号量
      • (一)进程互斥

《深入理解进程间通信:管道、消息队列、共享内存与信号量》

在操作系统中,进程间通信(Inter-Process Communication,IPC)是一个至关重要的概念,它允许不同的进程之间进行数据传输、资源共享、事件通知以及进程控制等操作。本文将详细介绍进程间通信的几种主要方式:管道、消息队列、共享内存和信号量。

一、进程间通信介绍

(一)进程间通信目的

  1. 数据传输:一个进程需要将它的数据发送给另一个进程。
  2. 资源共享:多个进程之间共享同样的资源。
  3. 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件,例如进程终止时要通知父进程。
  4. 进程控制:有些进程希望完全控制另一个进程的执行,如调试进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。

(二)进程间通信发展

  1. 管道:是 Unix 中最古老的进程间通信形式。
  2. System V 进程间通信:包括 System V 消息队列、System V 共享内存、System V 信号量。
  3. POSIX 进程间通信:包括消息队列、共享内存、信号量、互斥量、条件变量、读写锁等。

(三)进程间通信分类

  1. 管道:分为匿名管道和命名管道。
  2. System V IPC:包括消息队列、共享内存、信号量。
  3. POSIX IPC:包括消息队列、共享内存、信号量、互斥量、条件变量、读写锁等。

二、管道

(一)什么是管道

管道是从一个进程连接到另一个进程的一个数据流。在 Unix 系统中,管道的使用和文件一致,迎合了“Linux 一切皆文件思想”。

(二)匿名管道

  1. 功能和原型int pipe(int fd[2]);用于创建一无名管道。其中fd是文件描述符数组,fd[0]表示读端,fd[1]表示写端。成功返回 0,失败返回错误代码。
  2. 实例代码:从键盘读取数据,写入管道,读取管道,写到屏幕。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main( void )
{
    int fds[2];
    char buf[100];
    int len;
    if ( pipe(fds) == -1 )
    {
        perror("make pipe");
        exit(1);
    }
    // read from stdin
    while ( fgets(buf, 100, stdin) ) {
        len = strlen(buf);
        // write into pipe
        if ( write(fds[1], buf, len)!= len ) {
            perror("write to pipe");
            break;
        }
        memset(buf, 0x00, sizeof(buf));
        
        // read from pipe
        if ( (len=read(fds[0], buf, 100)) == -1 ) {
            perror("read from pipe");
            break;
        }
        // write to stdout
        if ( write(1, buf, len)!= len ) {
            perror("write to stdout");
            break;
        }
    }
}
  1. 用 fork 来共享管道原理:通过 fork 函数创建子进程,父子进程可以共享管道的文件描述符,从而实现进程间通信。

(三)管道特点

  1. 只能用于具有共同祖先的进程(具有亲缘关系的进程)之间进行通信。通常,一个管道由一个进程创建,然后该进程调用 fork,此后父、子进程之间就可应用该管道。
  2. 管道提供流式服务。
  3. 一般而言,进程退出,管道释放,所以管道的生命周期随进程。
  4. 一般而言,内核会对管道操作进行同步与互斥。
  5. 管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道。

(四)命名管道

  1. 创建命名管道
    • 命令行方法:使用mkfifo filename命令创建。
    • 程序创建:使用int mkfifo(const char *filename,mode_t mode);函数创建。
  2. 匿名管道与命名管道的区别
    • 匿名管道由pipe函数创建并打开;命名管道由mkfifo函数创建,打开用open
    • 一旦创建和打开完成后,它们具有相同的语义。
  3. 命名管道的打开规则
    • 如果当前打开操作是为读而打开 FIFO 时:
      • O_NONBLOCK disable:阻塞直到有相应进程为写而打开该 FIFO。
      • O_NONBLOCK enable:立刻返回成功。
    • 如果当前打开操作是为写而打开 FIFO 时:
      • O_NONBLOCK disable:阻塞直到有相应进程为读而打开该 FIFO。
      • O_NONBLOCK enable:立刻返回失败,错误码为ENXIO

三、共享内存

(一)共享内存简介

共享内存区是最快的 IPC 形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据。

(二)共享内存数据结构

struct shmid_ds {
    struct ipc_perm shm_perm; /* operation perms */
    int shm_segsz; /* size of segment (bytes) */
    __kernel_time_t shm_atime; /* last attach time */
    __kernel_time_t shm_dtime; /* last detach time */
    __kernel_time_t shm_ctime; /* last change time */
    __kernel_ipc_pid_t shm_cpid; /* pid of creator */
    __kernel_ipc_pid_t shm_lpid; /* pid of last operator */
    unsigned short shm_nattch; /* no. of current attaches */
    unsigned short shm_unused; /* compatibility */
    void *shm_unused2; /* ditto - used by DIPC */
    void *shm_unused3; /* unused */
};

(三)共享内存函数

  1. shmget 函数
    • 功能:用来创建共享内存。
    • 原型:int shmget(key_t key, size_t size, int shmflg);
    • 参数:
      • key:这个共享内存段名字。
      • size:共享内存大小。
      • shmflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的。
    • 返回值:成功返回一个非负整数,即该共享内存段的标识码;失败返回 -1。
  2. shmat 函数
    • 功能:将共享内存段连接到进程地址空间。
    • 原型:void *shmat(int shmid, const void *shmaddr, int shmflg);
    • 参数:
      • shmid:共享内存标识。
      • shmaddr:指定连接的地址。
      • shmflg:它的两个可能取值是SHM_RNDSHM_RDONLY
    • 返回值:成功返回一个指针,指向共享内存第一个节;失败返回 -1。
      • shmaddrNULL,核心自动选择一个地址。
      • shmaddr不为NULLshmflgSHM_RND标记,则以shmaddr为连接地址。
      • shmaddr不为NULLshmflg设置了SHM_RND标记,则连接的地址会自动向下调整为SHMLBA的整数倍。公式:shmaddr - (shmaddr % SHMLBA)
      • shmflg = SHM_RDONLY,表示连接操作用来只读共享内存。
  3. shmdt 函数
    • 功能:将共享内存段与当前进程脱离。
    • 原型:int shmdt(const void *shmaddr);
    • 参数:shmaddr:由shmat所返回的指针。
    • 返回值:成功返回 0;失败返回 -1。
    • 注意:将共享内存段与当前进程脱离不等于删除共享内存段。
  4. shmctl 函数
    • 功能:用于控制共享内存。
    • 原型:int shmctl(int shmid, int cmd, struct shmid_ds *buf);
    • 参数:
      • shmid:由shmget返回的共享内存标识码。
      • cmd:将要采取的动作(有三个可取值)。
      • buf:指向一个保存着共享内存的模式状态和访问权限的数据结构。
    • 返回值:成功返回 0;失败返回 -1。

四、消息队列

消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法。每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值。

特性方面,IPC 资源必须删除,否则不会自动清除,除非重启,所以 System V IPC 资源的生命周期随内核。

五、信号量

信号量主要用于同步和互斥。

(一)进程互斥

由于各进程要求共享资源,而且有些资源需要互斥使用,因此各进程间竞争使用这些资源,进程的这种关系为进程的互斥。系统中某些资源一次只允许一个进程使用,称这样的资源为临界资源或互斥资源。在进程中涉及到互斥资源的程序段叫临界区。

特性方面,IPC 资源必须删除,否则不会自动清除,除非重启,所以 System V IPC 资源的生命周期随内核。

进程间通信是操作系统中的重要概念,不同的通信方式各有特点,在实际应用中需要根据具体需求选择合适的方式来实现进程之间的高效通信和协作。


http://www.niftyadmin.cn/n/5664486.html

相关文章

C++:字符串string转成整型int

一、atoi atoi 是 C 标准库中的一个函数&#xff0c;全称是 ASCII to Integer&#xff0c;用于将字符串转换为整数。 函数定义 int atoi(const char *str);参数&#xff1a;str 是一个指向以 \0 结尾的字符串的指针。返回值&#xff1a;返回字符串转换后的整数。如果字符串中…

Flutter Android Package调用python

操作步骤 一、创建一个Flutter Package 使用以下指令创建一个Flutter Package flutter create --templateplugin --platformsandroid,ios -a java flutter_package_python 二、修改android/build.gradle文件 在buildscript——>dependencies中添加以下内容 //导入Chaqu…

【2024】前端学习笔记7-颜色-位置-字体设置

学习笔记 1.定义&#xff1a;css2.颜色&#xff1a;color3.字体相关属性&#xff1a;font3.1.字体大小&#xff1a;font-size3.2.字体风格&#xff1a;font - style3.3.字体粗细&#xff1a;font - weight3.4.字体族&#xff1a;font - family 4.位置&#xff1a;text-align 1.…

如何看待IBM中国研发部裁员?

​ 大家好&#xff0c;我是程序员小羊&#xff01; 前言&#xff1a; IBM中国研发部裁员及撤出背景分析 IBM&#xff08;International Business Machines&#xff09;作为全球科技巨头之一&#xff0c;其在中国市场的发展曾是中国信息技术产业的重要组成部分。近年来&#x…

图片转PDF技巧揭秘:四款高效工具推荐!

在数字化办公和学习的今天&#xff0c;将图片或其他文件格式转换为PDF已成为一种常见需求。以下是几款推荐的转换工具&#xff0c;它们各自具有独特的功能和使用体验&#xff0c;可帮助大家轻松实现图片转PDF及其他PDF相关操作。 福昕PDF转换大师&#xff08;365客户端&#x…

Yestar成都艺星引领行业星纪元:十大数字星品·高阶星技术震撼发布

近日&#xff0c;中国成都太古里Yestar十大数字星品高阶星技术AI科技3D Mapping全球发布会&#xff0c;震撼发布了十大数字星品高阶星技术升级&#xff0c;引领医美产业发展翻开崭新的一页。作为品牌成立19周年的庆典&#xff0c;这场科技与美学交融的盛会&#xff0c;标志着医…

AI绘画Stable Diffusion 自制素材工具: layerdiffusion插件—你的透明背景图片生成工具

大家好&#xff0c;我是灵魂画师向阳 今天给大家分享一款AI绘画的神级插件—LayerDiffusion。 Layerdiffusion是一个用于stable-diffusion-webui 的透明背景生成&#xff08;不是生成图再工具扣图&#xff0c;是直接生成透明背景透明图像&#xff09;插件扩展&#xff0c;它可…

战神诸神黄昏9月19日登录PC端! 手机怎么玩战神诸神黄昏

9月19日&#xff0c;《战神&#xff1a;诸神黄昏》正式登录PC端&#xff0c;这是一部动作冒险游戏。要是你想随时随地在手机或平板上也能玩《战神&#xff1a;诸神黄昏》&#xff0c;可以使用网易GameViewer远程帮你实现。 网易GameViewer远程作为一款专为游戏玩家打造的远程软…