进程间通讯方式

管道

管道是针对对本地计算机的两个进程之间的通信而设计的通信方式,管道建立后,实际获得两个文件描述符,一个读取另一个写入。最常见的IPC机制,通过PIPE系统调用。管道是单工的,数据只能向一个方向流动,需要双向通信时,需要建立起两个管道。管道的本质是内核中的缓存。

管道特性:

  1. 可以通过两个管道来创建一个双向的管道
  2. 管道是阻塞性的,当进程从管道中读取数据,若没有数据进程会阻塞
  3. 管道有大小限制,管道满再放则会报错
  4. 不完整管道
  • 当读一个写端已经关闭的管道时,在所有数据被读取后,read返回0,以表示到达了文件尾部
  • 如果写一个读端已经关闭的管道,刚产生信号SIGPIPE,如果忽略该信号或捕捉该信号并从处理程序返回,则write返回-1,同时errno设置为EPIPE

管道的分类

匿名管道

  1. 在关系进程中进行(父进程各子进程,兄弟进程之间)
  2. 由PIPE系统调用
  3. 管道位于内核空间,其实是一块缓存
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>/**
*Desc:扇形多线程之间管道通信
*author:xiao_dingo
*since:2018-03-07
*email:wwc0524@163.com
*/char *cmd1[3] = {"/bin/cat","/etc/passwd",NULL};
char *cmd2[3] = {"/bin/grep","root",NULL};int main(void){int fd[2];if(pipe(fd) < 0){perror("pipe error");}int i = 0;pid_t pid;for(;i < 2; i++){pid = fork();if(pid < 0){perror("fork error");exit(1);}else if(pid == 0){//child processif(i == 0){close(fd[0]);//将标准输出重定向到管道的写端if(dup2(fd[1],STDOUT_FILENO) != STDOUT_FILENO){perror("dup2 error");}close(fd[1]);if(execvp(cmd1[0],cmd1) < 0){perror("execvp error");exit(1);}break;}if(i == 1){close(fd[1]);//将标准输入重定向到管道的读端if(dup2(fd[0],STDIN_FILENO) != STDIN_FILENO){perror("dup2 error");}       close(fd[0]);if(execvp(cmd2[0],cmd2) < 0){perror("execvp error");exit(1);}break;}}else{//parent processif(i == 1){close(fd[0]);close(fd[1]);wait(NULL);wait(NULL);}}}exit(0);
}
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>/**
*Desc:不完整管道之间操作
*author:xiao_dingo
*since:2018-03-08
*email:wwc0524@163.com
*/void sig_handler(int signo){if(signo == SIGPIPE){printf("sigpipe occured\n");}
}void main(void){int fd[2];if(pipe(fd) < 0){perror("pipe error");exit(1);}pid_t pid;if((pid = fork()) < 0){perror("fork error");exit(1);}else if(pid > 0){//parent processsleep(5);close(fd[0]);if(signal(SIGPIPE,sig_handler) == SIG_ERR){perror("signal sigpipe error");exit(1);}char *s = "1234";if(write(fd[1],s,sizeof(s)) != sizeof(s)){fprintf(stderr,"%s,%s\n",strerror(errno),(errno == EPIPE) ? "EPIPE" : ",UNKNOW");}}else{//child processclose(fd[0]);close(fd[1]);}
}

命名管道(FIFO)

  1. 两个没有任何关系的进行之间通信可以通过命名管道进行数据传输,本质是内核中的一块缓存,在文件系统中以一个特殊的设备文件(管道文件)存在。在文件系统中的管道文件只有一个索引块存放文件路径,没有数据块,所有数据存放在内核中。
  2. 通过系统调用mkfifo创建
  3. 命名管道必须读和写同时打开,否则会进入阻塞
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char* pathname,mode_t mode);

消息队列

System v IPC对象(消息队列,共享内存和信号量)存在于内核中而不是文件系统中,由用户控制释放(用户管理IPC对象的生命周期),不像管道和释放由内核控制。IPC对象通过标识符来引用和访问,所有的IPC对象在内核空间有唯一标识ID,在用户空间的唯一标识称为Key

消息队列特性

  1. 消息队列是内核中的一个链表
  2. 用户进程将数据传输到内核后,内核重新添加一些如用户ID,组ID,读写进程的ID和优先集等相关信息后并打成一个数据包称为消息
  3. 允许一个或者多个进程往消息队列中写消息和读消息,但一个消息只能被一个进程读取,读取完毕就自动删除
  4. 消息队列具有一定的FIFO的特性,消息可以按照顺序发送到队列中,也可以几种不同的方式从队列中读取,消息队列在内核中用一个唯一的IPC标识ID表示
  5. 消息队列的实现包括创建和打开队列,发送消息,读取消息,控制消息队列四种操作
  6. linux 系统查看命令ipcs 删除ipcrm
#include <sys/msg.h>
int msgget(key_t key,int flag);//查询
int msgctl(int msgid,int cmd,struct msgid_ds *buf);//控制
int msgsnd(int magid,const void *ptr,szie_t nbytes,int flag);//发送
ssize_t msgrvc(int msgqid,void *ptr,size_t nbytes,long type,int flag);//接收

共享内存

共享内存允许系统内两个或多个进程共享同一块内存空间,并且数据不用在客户进程和服务器进程间复制,因此共享内存是通信速度最快的一种IPC。
实现的机制简单描述如下:一个进程在系统中申请开辟了一块共享内存空间,然后使用这个共享内存空间的各个进程分别打开这个共享内存空间,并将这个内存空间映射到自己的进程空间上,这样各个进程就可以共同使用这个共享内存空间,就如同使用自己进程地址空间的内存一样
要实现共享内存空间,内核做了许多工作:比如给每个共享内存块分发一个“身份证”、允许用户进程将共享内存映射到各自的地址空间上、在进程提出申请以后将共享内存和进程地址空间脱离,并在适当的时候讲共享内存删除,让其回到可以被创建的状态。
用户利用共享内存实现进程间的通信,实际上就是使用内核提供的服务完成对共享内存的建立、映射、脱离、删除等。当建立并映射成功以后,进程间就能通过共享内存实现数据的交互。

内核提供的服务

/**
*shmget实现共享内存的建立或者打开
*当共享内存的键值key 尚未存在时,调用这个函数并且指定shmflg 参数为IPC_CREAT 可以创建一个大小为 size 的共享内存空间。假设key指定的共享内存已经存在,调用这个函数可以打开这个共享内存,但不会创建。
*
*/
int shmget(key_t key, size_t size, int shmflg);
/**
*该函数将一个共享内存空间映射到调用进程的地址空间上,并且返回在进程地址空间中的地址。用户拿到改地址后就可以通过这个地址间接的访问共享内存。
*shmid 参数就是shmget 函数的返回值,shmaddr 参数实际上是指出了共享内存映射到进程地址空间上的位置,但是我们一般不会指定这个地址,而是令其为NULL ,让内核选择一个合适的地址。shmflg 参数是配合着shmaddr 参数使用的,在shmaddr 为NULL时就变得没有实际意义,因此通常指定为0
*/
void *shmat(int shmid,const void* shmaddr,int shmflg);
/**
*这个函数将一个进程已经映射了的共享内存脱离进程地址空间。shmaddr 参数就是在进程地址空间的地址,实际就是shmat 函数的返回值
*/
int shmdt(const void* shmaddr);
/**
*此函数实际上有很多的功能,但是我们通长用它将一个已经创建了的共享内存删除,所谓删除实际就是将它放回可以被创建的共享内存队列中。指定cmd 参数为IPC_RMID,就可以将shmid键值指定的共享内存删除,而buf实际上是可以获取这共享内存在内核中的状态,如果不想了解可以指定为0
*/
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

进程信号量

用于进程间的huchi与同步,每种共享资源对应一个信号量,为了便于大量共享资源的操作引入了信号量集,可对所有信息量一次性操作,对信号量集中所有操作可以要求全部成功,也可以部分成功。
它是一个特殊变量,只允许对它进行等待和发送信号这两种操作。

  • P(信号量变量sv):等待。如果sv大于0,减小sv。如果sv为0,挂起这个进程的执行。
  • V(信号量变量sv):发送信号。如果有进程被挂起等待sv,使其恢复执行。如果没有进行被挂起等待sv,增加sv。
#include  <sys/sem.h>
/**
*
*
*/
int semget(key_t key,int nsems,int semflg);

LINUX inner-process communication相关推荐

  1. linux ps(process status) 命令详解

    linux ps(process status) 命令详解 功能说明:报告程序状况. 语 法:ps [-aAcdefHjlmNVwy][acefghLnrsSTuvxX][-C <指令名称> ...

  2. 进程间基于共享存储区的通信_IPC(进程间通讯):inter process communication

    管道 (1)管道是半双工的,数据只能向一个方向流动:需要双方通信时,需要建立起两个管道: (2)只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程): (3)**单独构成一种独立的文件系统:**管道 ...

  3. [archlinux] linux boot process/order/stage

    信息量好大 --! 神教读物,无人能比: https://wiki.archlinux.org/index.php/Arch_boot_process IBM的高质量文档 https://www.ib ...

  4. C# 进程间通信 (Process Communication in C#)

    简单介绍 进程间通信就是在不同进程之间传播或交换信息.这里总结了Windows系统中的进程间通信的一些方式,用C#实现了出来. C# 进程间通信的多种方式 Clipboard COM File Map ...

  5. Linux下进程通信知识点学习笔记(一)

    4种主要事件导致进程创建: 系统的初始化: 执行了正在运行的进程所调用的进程创建系统调用: 用户请求创建一个进程: 一个批处理作业的初始化: 进程的终止: 正常退出: 出错退: 严重错误: 被其他进程 ...

  6. linux进程及作业管理实验,Linux 进程及作业管理(示例代码)

    Linux 进程及作业管理 概述: 一.进程的相关概念: 1.相关定义:内核的功用:   进程管理.文件系统.网络功能.内存管理.驱动程序.安全功能等: 通俗的来说进程是运行起来的程序.唯一标识进程的 ...

  7. 鸟哥的Linux私房菜(基础篇)- 第二十六章、Linux 核心编译与管理

    第二十六章.Linux核心编译与管理 最近升级日期:2009/09/18 我们说的 Linux 其实指的就是核心 (kernel) 而已.这个核心控制你主机的所有硬件并提供系统所有的功能,所以说,他重 ...

  8. 七、Linux脚本进阶和进程管理

    一.进程 进程:init(1)-->系统的第一个进程,通过fork调用其他进程,自身由内核发起. 通过pstree可以查看进程之间的父子关系. [root@localhost ~]# pstre ...

  9. linux基础篇-系统中进程相关概念

    进程概念  内核的功用:进程管理.文件系统.网络功能.内存管理.驱动程序.安全功能等  Process: 运行中的程序的一个副本,是被载入内存的一个指令集合进程ID(Process ID,PID) ...

  10. OS / linux / 互斥锁实现原理(futex)

    零.前言 所谓的锁,在计算机里本质上就是一块内存空间.当这个空间被赋值为 1 的时候表示加锁了,被赋值为 0 的时候表示解锁了,仅此而已. 多个线程抢一个锁,就是抢着要把这块内存赋值为 1 .在一个多 ...

最新文章

  1. SessionID 的本质
  2. 超级计算机预测南方下雪,南方九省即将大雪纷飞?超级计算机:可能性增加,但还没有确定...
  3. photoshop cc_如何使用Photoshop CC将图片变成卡通
  4. linux 端口tnpl,Linux和Windows端口占用情况查看
  5. knn机器学习算法_K-最近邻居(KNN)算法| 机器学习
  6. 【重点】Batch Normalization的诅咒
  7. 最简单解决jpa自动生成表后字段乱序问题
  8. 【虚拟机】VirtualBox 安装 Windows 11 虚拟机简介
  9. 采用加速度传感器的角度测量仪系统硬件电路设计_温度传感器电路
  10. 如何实现android设备进入recovery界面后自动重启
  11. python和java哪个好就业-计算机专业选Java和Python哪个前景好点?
  12. 进化树构建之邻接法(Neighbor-Joining)的介绍
  13. k--最近邻算法(KNN)
  14. 【原创】C#玩高频数字彩快3的一点体会
  15. java2.0qq同步_qq同步助手2.0 apk下载
  16. StarlingX 前世今生 -- (汇总了网上的一些资料)
  17. oracle 快照过旧:回退段号,ORA-01555: 快照过旧: 回退段号 39 (名称为 _SYSSMU39_3029844184$) 过小...
  18. WordPress如何采集WordPress采集插件推荐
  19. 普中PZ6808L-F4开发板TFTLCD显示屏使用笔记
  20. 数制转换的概念和转换

热门文章

  1. 设计模式(3)-装扮你的类(装饰模式)
  2. 数据备份软件,BackBone,NetVault,网络存储备份,系统集成
  3. 如何在数字前面填充0,在股票代码前面补上0的三种方法
  4. 工作中总结的一些C#小经验,随时更新
  5. 小问题(可能持续更新)
  6. 压缩感知 compressive sensing(转)
  7. 2010年厦门商报报导《监控》小说
  8. Microsoft Expression Web Beta 1
  9. R语言如何画个性化词云图
  10. python事件驱动编程_Python事件驱动编程