一 Linux进程间通信

进程间通信概念:进程是一个独立的资源分配单位,不同进程之间有关联,不能在一个进程中直接访问另一个进程的资源 。

  • 进程和进程之间的资源是相互独立的,一个进程不能直接访问另外一个进程的资源 , 但是进程和进程之间不是相互独立的 。
通信目的:
  • 数据传输:一个进程需要将它的数据发送给另一个进程 。
  • 资源共享:多个进程之间共享同样的资源 。
  • 通知事件:一个进程需要向另一个或一组进程发送消息 , 通知某些或某个进程发生了某种事件(如进程终止时要通知父进程) 。
  • 进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常 , 并能够及时知道它的状态改变 。
如何实现进程通信?
要让两个不同的进程实现通信,前提条件是让它们看到同一份资源 。所以要想办法让他们看到同一份资源,就需要采取一些手段,可以分为下面几种 。
通信方式分类1.管道
  • 匿名管道pipe
  • 命名管道
2.System V IPC
  • System V 消息队列
  • System V 共享内存
  • System V 信号量
3.POSIX IPC
  • 消息队列
  • 共享内存
  • 信号量
  • 互斥量
  • 条件变量
  • 读写锁
管道概念:我们把一个进程连接到另一个进程的一个数据流称为一个“管道” 。
管道的特点:
  • 数据只能从管道的一端写入,从另一端读出
  • 写入管道的数据遵循先入先出的原则
  • 管道所传达的数据是无格式的 , 这要求管道的读出方和写入方必须事先约定好数据的格式
  • 管道不是普通的文件,不属于某个文件系统,只存在于内存中
  • 管道读数据是一次性的,数据一旦被读走,它就从管道中抛弃,释放空间
  • 管道是一种特殊的文件类型,会在应用层打开两个文件描述符fd[0]对应的是写端 , fd[1]对应的是读端
  • 管道只能服务于有血缘关系的两个进程

一 Linux进程间通信

文章插图
匿名管道创建匿名管道-----pipe系统调用intpipe(int pidefd[2]);
功能:创建无名管道
参数:pipefd:为int类型数组的首地址 , 其存放了管道的文件描述符pipefd[0]、pipefd[1]
当一个管道建立的时候,他会创建两个文件描述符fd[0]和fd[1] 。其中fd[0]固定用于读管道,而fd[1]固定用于写管道 。
返回值:成功:0失败:-1
  • 文件描述符就是操作系统为了高效管理已经打开文件所创建的一个索引(文件描述符在前面的文章介绍过)
匿名管道创建原理:
调用pipe函数后 , OS会在fd_array数组中分配两个文件描述符给管道,一个是读,一个是写,并把这两个文件描述符放到用户传进来的数组中 , fd[0]代表管道读端,fd[1]代表管道写端 。这样一个管道就创建好了 。
一 Linux进程间通信

文章插图
实例演示:
实例1:观察两个文件描述符的值
#include <stdio.h>#include <unistd.h>int main(){ int pipefd[2]; int ret = pipe(pipefd); if (ret == -1){// 管道创建失败perror("make piep");//用于退出进程exit(-1); } // 成功返回0 // pipefd[0] 代表读端 // pipefd[1] 代表写端 printf("fd[0]:%d, fd[1]:%d\n", pipefd[0], pipefd[1]); return0;}运行结果如下:
一 Linux进程间通信

文章插图
显然,pipefd这个数组里面放的是两个文件描述符,分别是3和4 , 因为0 , 1,2文件描述符在进程创建的时候会由系统自动创建 。
实例2:尝试使用管道读写数据
#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>int main(){int pipefd[2];int ret = pipe(pipefd);if (ret == -1){// 管道创建失败perror("make piep");exit(-1);}char buf[64] = "hello world";// 写数据write(pipefd[1], buf, sizeof(buf)/sizeof(buf[0]));// 读数据memset(buf,0,sizeof(buf));// 清空bufssize_t s = read(pipefd[0], buf, 11);buf[s] = '\0';printf("%s\n", buf);return 0;}//成功输出hello world可以看见对管道的操作,实际上就是对两个读写文件的操作,本质就是对文件的操作和使用 。
管道的本质Linux下一切皆文件,看待管道 , 其实时可以像看待文件一样 。且管道和文件使用方法是一致的 。管道的生命周期随进程 。

推荐阅读