进程间的通信(IPC)

进程间的用户地址空间是相互独立的,所以进程间通信必须要通过内核,在内核空间中开辟一块缓冲区,进程1把用户空间的数据copy到内核缓冲区,进程2再从内核缓冲区中将数据copy到属于自己的用户空间,这就是进程间的通信。(IPC)

一、管道

(a)无名管道

  /**
  *input:文件描述符数组
  *return 大于0等于创建成功
  */
  int pipe(fddes[2]);//在内核中开辟管道
  pid=fork();//创建子进程,将父进程创建的无名管道clone到子进    
  程中,读写端口的文件描述符也是一样的

无名管道是有血缘关系进程间的通信手段,通过以上的函数在内核中创建环形队列来进行半双工的读写通信;fddes[0]指向管道的读端口,fddes[1]指向管道的写端口。

#include <stdio.h>
#include <unistd.h>
#define MAXLINE 80

int main(void){
        int fd[2];
        pid_t pid;
        char line[MAXLINE];
        if(pid=pipe(fd)<0){
        printf("error");
        exit(1);
        }

        if(pid=fork()>0){
        close(fd[0]);//关闭父进程的读端
        write(fd[1],"Hello World!\n",12);
        wait(NULL);
        }else{
        close(fd[1]);//关闭子进程的写端
        int n=read(fd[0],line,MAXLINE);
        write(STDOUT_FILENO,line,n);
        }
}

管道里面是字节流,父子进程都写、都读,就会导致内容混在一起,对于读管道的一方,解析起来就比较困难。常规的使用方法是父子进程一方只能写入,另一方只能读出,管道变成一个单向的通道,以方便使用。如图下图所示,父进程放弃读,子进程放弃写,变成父进程写入,子进程读出,成为一个单向通道。


单向通道

(b)有名管道(FIFO)

 /**
 *p1 磁盘文件路径名
 *p2 权限
 **/
 #include <sys/types.h>
 #include <sys/stat.h>
 int mkfifo(const char *pathname, mode_t mode);

创建有名管道使得无血缘进程间得以通信,有名管道严格遵循先进先出(first in first out)。有名管道以磁盘文件的方式存在,可以实现本机任意两个进程通信。FIFO内核实现时可以支持双向通信。(pipe单向通信,因为父子进程共享同一个file结构体)


命名管道

二、共享内存(MMAP)

mmap可以把磁盘文件的一部分直接映射到内存,这样文件中的位置直接就有对应的内存地址,对文件的读写可以直接用指针来做而不需要read/write函数。


MMAP
#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
int munmap(void *addr, size_t length);

如果addr参数为NULL,内核会自己在进程地址空间中选择合适的地址建立映射。如果addr不是NULL,则给内核一个提示,应该从什么地址开始映射,内核会选择addr之上的某个合适的地址开始映射。建立映射后,真正的映射首地址通过返回值可以得到。len参数是需
要映射的那一部分文件的长度。off参数是从文件的什么位置开始映射,必须是页大小的整数倍(在32位体系统结构上通常是4K)。filedes是代表该文件的描述符。

prot参数有四种取值:

  • PROT_EXEC表示映射的这一段可执行,例如映射共享库
  • PROT_READ表示映射的这一段可读
  • PROT_WRITE表示映射的这一段可写
  • PROT_NONE表示映射的这一段不可访问

flag参数有很多种取值,这里只讲两种,其它取值可查看mmap(2)

  • MAP_SHARED多个进程对同一个文件的映射是共享的,一个进程对映射的内存做了修改,另一个进程也会看到这种变化。
  • MAP_PRIVATE多个进程对同一个文件的映射不是共享的,一个进程对映射的内存做了修改,另一个进程并不会看到这种变化,也不会真的写到文件中去。
    如果mmap成功则返回映射首地址,如果出错则返回常数MAP_FAILED。当进程终止时,该进程的映射内存会自动解除,也可以调用munmap解除映射。munmap成功返回0,出错返回-1。

三、socket(套接字)

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 前言 Linux环境下,进程地址空间相互独立,每个进程各自有不同的用户地址空间。任何一个进程的全局变量在另一个进程...
    Sharkchilli阅读 1,131评论 0 0
  • 主要讲解进程间通信方式,包含管道 FIFO命名管道 消息队列 同步(互斥锁、条件变量、信号量、读写锁、fcntl记...
    FengyunSky阅读 438评论 0 1
  • Linux进程通信实现机制有很多,也有各自优缺点和适用场景,关于她们之间的对比,等各种通信机制一一介绍后,再来一个...
    batbattle阅读 4,243评论 3 13
  • 一.管道机制(pipe) 1.Linux的fork操作 在计算机领域中,尤其是Unix及类Unix系统操作系统中,...
    Geeks_Liu阅读 3,856评论 1 9
  • 01概述 1.1 发展 Linux进程间通信(IPC)大致发展如下: 早期UNIX进程间通信、基于System ...
    程序员姜戈阅读 504评论 0 0

友情链接更多精彩内容