首页
学习
活动
专区
圈层
工具
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

linux ipc 编程

一、基础概念

  1. 定义
    • Linux中的IPC(Inter - Process Communication,进程间通信)是指不同进程之间交换数据、共享信息的机制。由于每个进程都有自己独立的地址空间,进程间不能直接访问彼此的数据,所以需要特定的IPC机制来实现通信。
  • 目的
    • 主要目的是实现进程之间的数据共享、同步操作以及消息传递等功能。例如,在一个多任务的操作系统中,不同的应用程序或者同一应用程序的不同进程可能需要协同工作,IPC机制就提供了这种协同的途径。

二、相关优势

  1. 资源共享
    • 多个进程可以共享数据,如共享内存允许进程直接访问同一块物理内存区域,提高了数据的共享效率,避免了数据的多次拷贝。
  • 任务协作
    • 进程间可以通过信号量进行同步操作,确保多个进程对共享资源的有序访问。例如,在生产者 - 消费者模型中,生产者进程生产数据放入缓冲区,消费者进程从缓冲区取数据,信号量可以用来控制缓冲区的空位和满位情况,保证两个进程的正确协作。
  • 灵活性
    • 不同的IPC机制适用于不同的场景。消息队列适合于异步消息传递,管道适合于父子进程间的单向数据传输等,开发者可以根据具体需求选择合适的机制。

三、类型及应用场景

  1. 管道(Pipe)
    • 类型特点
      • 管道是一种半双工的通信方式,数据只能单向流动,并且只能在具有亲缘关系(如父子进程)的进程间使用。
    • 应用场景
      • 常用于简单的进程间数据传递,例如在一个命令行管道操作中,ls | grep "txt"ls命令的输出通过管道传递给grep命令进行处理。
    • 示例代码(C语言)
代码语言:txt
复制
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

int main() {
    int pipefd[2];
    pid_t pid;
    char buffer[256];

    if (pipe(pipefd)== -1) {
        perror("pipe");
        exit(EXIT_FAILURE);
    }

    pid = fork();
    if (pid < 0) {
        perror("fork");
        exit(EXIT_FAILURE);
    } else if (pid == 0) {
        // 子进程,关闭读端,向写端写入数据
        close(pipefd[0]);
        const char *message = "Hello from child process";
        write(pipefd[1], message, strlen(message)+1);
        close(pipefd[1]);
        exit(EXIT_SUCCESS);
    } else {
        // 父进程,关闭写端,从读端读取数据
        close(pipefd[1]);
        read(pipefd[0], buffer, sizeof(buffer));
        printf("Parent received: %s
", buffer);
        close(pipefd[0]);
    }
    return 0;
}
  1. 消息队列(Message Queue)
    • 类型特点
      • 消息队列是一种基于消息的通信方式,进程可以将消息发送到队列中,其他进程可以从队列中接收消息。它支持多对多的通信模式,并且消息有类型区分。
    • 应用场景
      • 在分布式系统或者多进程的任务调度系统中,用于异步消息传递。例如,一个日志收集进程可以从多个应用程序进程的消息队列中接收日志消息。
    • 示例代码(C语言,使用System V消息队列)
代码语言:txt
复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

struct msgbuf {
    long mtype;
    char mtext[100];
};

int main() {
    key_t key;
    int msgid;
    struct msgbuf sbuf, rbuf;

    key = ftok(".", 'a');
    msgid = msgget(key, 0666 | IPC_CREAT);

    // 发送消息
    sbuf.mtype = 1;
    strcpy(sbuf.mtext, "Hello from sender");
    msgsnd(msgid, &sbuf, sizeof(sbuf.mtext), 0);

    // 接收消息
    msgrcv(msgid, &rbuf, sizeof(rbuf.mtext), 1, 0);
    printf("Received: %s
", rbuf.mtext);

    msgctl(msgid, IPC_RMID, NULL);
    return 0;
}
  1. 共享内存(Shared Memory)
    • 类型特点
      • 共享内存是允许多个进程共享同一块物理内存区域的IPC机制。它是所有IPC机制中速度最快的,因为数据不需要在进程间进行拷贝。但是需要配合信号量等机制来保证数据的一致性。
    • 应用场景
      • 在需要对大量数据进行高效共享的场景,如图形处理程序中多个进程共享图像数据,或者数据库系统中多个进程共享数据缓存。
    • 示例代码(C语言,使用System V共享内存)
代码语言:txt
复制
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>

int main() {
    key_t key;
    int shmid;
    char *str;

    key = ftok(".", 'b');
    shmid = shmget(key, 1024, 0666 | IPC_CREAT);
    str = (char *) shmat(shmid, (void *)0, 0);

    strcpy(str, "Hello from shared memory");

    printf("Data written in memory: %s
", str);

    shmdt(str);
    shmctl(shmid, IPC_RMID, NULL);
    return 0;
}
  1. 信号量(Semaphore)
    • 类型特点
      • 信号量是一个整型变量,主要用于进程间的同步操作。它可以用来控制多个进程对共享资源的访问数量。
    • 应用场景
      • 在多进程并发访问有限资源(如打印机、文件等)时,用于防止竞争条件。例如,在生产者 - 消费者模型中,控制缓冲区的访问。
    • 示例代码(C语言,使用System V信号量)
代码语言:txt
复制
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

union semun {
    int val;
    struct semid_ds *buf;
    unsigned short *array;
};

int main() {
    key_t key;
    int semid;
    union semun arg;
    struct sembuf sb = {0, -1, SEM_UNDO};

    key = ftok(".", 'c');
    semid = semget(key, 1, 0666 | IPC_CREAT);
    arg.val = 1;
    semctl(semid, 0, SETVAL, arg);

    // 模拟临界区访问
    semop(semid, &sb, 1);
    printf("Entering critical section
");
    sleep(2);
    printf("Exiting critical section
");
    sb.sem_op = 1;
    semop(semid, &sb, 1);

    semctl(semid, 0, IPC_RMID, arg);
    return 0;
}

四、常见问题及解决方法

  1. 数据不一致问题(以共享内存为例)
    • 原因
      • 当多个进程同时访问和修改共享内存中的数据时,如果没有适当的同步机制(如信号量),就会导致数据不一致。例如,两个进程同时读取一个变量的值,然后分别进行加1操作,最后写回共享内存,这样就会导致这个变量的值只增加了1而不是2。
    • 解决方法
      • 使用信号量或者互斥锁来保证对共享内存的互斥访问。在访问共享内存之前,进程获取信号量(使得其他进程不能访问),访问结束后释放信号量。
  • 死锁问题(在信号量或多进程同步场景下)
    • 原因
      • 当多个进程互相等待对方释放资源时就会发生死锁。例如,进程A持有资源1并请求资源2,而进程B持有资源2并请求资源1。
    • 解决方法
      • 遵循资源分配顺序原则,确保所有进程以相同的顺序请求资源;或者使用超时机制,在等待资源一定时间后放弃并重新尝试。
  • 消息丢失问题(消息队列)
    • 原因
      • 如果消息队列已满,发送方进程发送消息时可能会失败而导致消息丢失;或者在接收方进程异常退出时没有正确处理未接收的消息。
    • 解决方法
      • 对于队列满的情况,可以采用非阻塞发送或者循环发送直到成功;对于接收方异常退出的情况,可以使用持久化消息队列或者对消息进行备份处理。
页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

【Linux】SystemV IPC

系统调用接口 (1)创建共享内存 首先不管怎样,我们得在系统里创建一个共享内存,在 Linux 中创建一个共享内存的系统接口为:shmget(),手册如下: 其中返回值,成功返回共享内存的标识符,是一个整数...IPC_CREAT | IPC_EXCL 表示创建一个共享内存,如果不存在就直接创建,存在就出错返回。那么这两个选项组合使用,就能确保我们申请的共享内存一定是一个新的!...| IPC_EXCL | 0666); } // 获取共享内存 int GetShm() { return GetShareMem(IPC_CREAT...三、IPC在内核中的数据结构设计 在介绍 IPC 在内核中的数据结构设计前,我们再先认识一个进程间通信的方式,就是信号量,信号量也和上面学的两个进程间通信方式一样,都是 SystemV 标准的,所以它们都有共同的标准...xxx_perm,如下: 共享内存 消息队列 信号量 其中系统中的所有 IPC 资源是被整合在操作系统的一个 IPC 模块当中的。

16010
  • 【Linux】IPC 进程间通信(二)(共享内存)

    具体步骤如下: 创建共享内存区域:一个进程首先通过系统调用(如 shmget 在Unix/Linux中)请求操作系统为它创建一个共享内存区域。...IPC_CREAT:如果共享内存段不存在,则创建它;如果存在,则返回其标识符 IPC_EXCL:单独使用没意义,只有和IPC_CREAT组合才有意义 IPC_CREAT | IPC_EXCL:如果共享内存段不存在则创建它...内核当中获取共享内存的属性 cmd: IPC_STAT:获取共享内存段的当前关联值。 IPC_SET:设置共享内存段的当前关联值(需要足够权限)。 IPC_RMID:删除共享内存段。...| IPC_EXCL | gmode); } int GetShm() { return CreateShmHelper(IPC_CREAT); }...复杂性:管理共享内存的生命周期和同步机制需要额外的编程工作,这比管道或消息队列等简单的IPC机制更复杂 地址空间限制:每个进程只能将共享内存映射到自己的虚拟地址空间,而虚拟地址空间的大小是有限的,

    17910

    Android跨进程通信IPC之1——Linux基础

    这部分是临时加进来的,是在后面的Binder驱动里面会用到,原来是打算加到"Android跨进程通信IPC之1——Linux基础"里面,不过由于简书的篇幅限制,我加到这里来了。...四、Linux的跨进程通信(IPC)概述 (一)、跨进程通信(IPC)的目的 跨进程通信(IPC)的目的主要如下: 数据传递 一个进程需要将它的数据发送给另外一个进程,发送的数据量在一个字节到几M...(二)、Linux 进程间通信(IPC)的发展 ** Linux **下的跨进程通信手段基本上是从Unix平台上的进程通信手段继承而来。...匿名管道(pipe)是Linux支持的最初Unix IPC形式之一,具有以下特点: 匿名管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立两个管道; 只能作用于父子进程或者兄弟进程之间...在Linux中,VFS采用的是面向对象的编程方法。

    1.7K30

    UNIX IPC

    @(linux 编程) 一、 消息传递 pipe 管道一般为有亲缘关系进程提供单路数据流, 通过pipe(int fd[2])创建, 返回两个文件描述符, fd[0] 用于读,fd[1]用于写。...line, MAXLINE); write(STDOUT_FILENO, line, n); } return 0; } 以下提供一个开源例子, Webbench 是一个在linux...linux 默认read/write操作是阻塞的, 可以在打开的时候设置O_NONBLOCK为非阻塞(或者之后使用 fcntl 函数进行设置)。...System V信号量 System V 信号量一般指的是计数信号量集 三、共享内存 共享内存是可用 IPC 形式中最快的, 因为共享内存中的单个数据副本对于共享该内存区的所有线程或者进程都是可用的,对共享内存进行操作需要其他同步措施保证...System V共享内存 参考 《UNIX网络编程卷2 : 进程间通信》 IPC分类 Poxis 消息队列 System V 消息队列 文件映射

    1.4K20

    linux下IPC latency 进程间通讯延迟测试结果

    p=40 CPU name : Intel(R) Xeon(R) CPU E5405 @ 2.00GHz processor : 4 cpu MHz : 1995.021 IPC latency: IPC...  10K       9us localhost tcp   10K       11us pipe        10K       6us remote TCP   10K       13us IPC...throughput: IPC TYPE:   MessageSize:   Average throughput/msg:   Average throughput/M: unix socket   ...        9112 Mb/s pipe        10K        146724 msg/s          11737 Mb/s 测试代码: http://github.com/rigtorp/ipc-bench...想在linux下选择一个IPC,主要倾向于unix socket,ipc-bench测试下来 感觉更有底了,10K数据传输9us的延时在大多数应用中都可以接受了, 这样某些应用可以使用类似于Nginx

    3.1K40

    Linux笔记(16)| 进程同步机制——管道和IPC

    今天要分享的是Linux进程的同步机制,包括管道和IPC。之前学习的信号也有控制进程同步的作用,但是信号仅仅传输很少的信息,而且系统开销大,所以这里再介绍几种其他的进程同步机制。...在之前的一篇文章中有提到相关内容,但是当时没有详细展开,可以回顾一下:Linux笔记(10)| 进程概述。...管道是Linux下最常见的进程间的通信方式之一,它是在两个进程之间实现一个数据流通的通道。它有以下特点: 1、管道一般是半双工的,数据只能向一个方向流动。...所以,根据关键字和标识符可以唯一确定一个IPC结构。 IPC的关键字一般可以使用IPC_PRIVATE,也可以使用ftok函数获得,他们有一些区别,后面会提到。...同时设置IPC_CREAT位和IPC_EXCL位,如果对象不存在就创建,如果已经存在,则返回错误。 这和文件操作函数open是类似的。 接下来介绍一下各个IPC对象涉及到的API函数。

    2K20

    IPC$横向移动

    IPC$简单介绍 IPC$(Internet Process Connection)是共享“命名管道”的资源,它是为了让进程间通信而开放的命名管道,通过提供可信任的用户名和口令,连接双方可建立安全通道...IPC是winNT/2000的一项新功能,它有一个特点,即在同一时间内,两个IP之间只允许建立一个连接,winNT/2000在提供IPC功能的同时,在初次安装系统时还打开了默认共享,即所有的逻辑共享(c...,因此一般来讲,ipc连接是需要139或445端口来支持的。...\ipc$ "1234Qwer!...$记录 于此同时,我们还需要删除创建的IPC$记录: net use '名称' /del /y 在删除ipc时,要确认删除的是自己创建的ipc,在使用schtasks命令时会在系统中留下日志文件C:\

    5.1K30

    扫码

    添加站长 进交流群

    领取专属 10元无门槛券

    手把手带您无忧上云

    扫码加入开发者社群

    相关资讯

    热门标签

    活动推荐

      运营活动

      活动名称
      广告关闭
      领券