一,Linux下进程间通信的几种主要手段简介:

1,管道(Pipe)及有名管道(named pipe)

  管道可用于具有亲缘关系进程间的通信

  有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信;

2,信号(Signal):,

3,消息队列(Message):

  消息队列是消息的链接表,包括Posix消息队列system V消息队列

  消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。

4,共享内存:

  使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。

5,信号量(Semaphore):

  主要作为进程间以及同一进程不同线程之间的同步手段。

6,套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。

二,管道

  参考https://www.cnblogs.com/cfans1993/p/5657478.html

    https://www.cnblogs.com/52php/p/5878029.html

    https://www.cnblogs.com/52php/p/5840229.html

  管道是Linux支持的最初Unix IPC形式之一,具有以下特点:

  • 管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;
  • 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);
  • 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中。
  • 数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。

2.1 pipe

#include <unistd.h>
int pipe(int fd[2])

  • 专用于父子进程通信, 函数原型 int pipe(int fd[2])
  • fd[0]表示输入, fd[1]表示输出
  • 如果父子进程要双向通信, 可以通过类似信号的功能进行控制, 也可以简单地打开两个pipe
  • 用read,Wright 读写
  • 只有阻塞方式

当管道的写端存在时,数据不能超过PIPE_BUF 注:(不同系统要求的PIPE_BUF不一样,通常为512字节)。

2.2  popen和pclose

#include <stdio.h>
FILE* popen(const char *command, const char *open_mode);
int pclose(FILE *stream_to_close);

    • 函数原型FILE *popen(const char *cmdstring, const char *type) , type的参数为"r"或"w"
    • 用于父子进程通信, popen会自动fork子进程、创建pipe和关闭不需要的pipe端
    • popen的实现有可理解为execl("/bin/sh","sh","-c",cmdstring,NULL)
    • 当父进程向子进程发送信息时(type="w"), 实际就是向shell发送命令;
      当父进程从子进程获取信息时(type="r"), 实际就是读取shell的执行结果
    • 虽然popen的返回是FILE,但关闭是要用pclose(fp)
    • 用fread 和fwright写
    • 只有阻塞方式
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h> #define MAXLINE 1024
void err_quit(const char *str){
perror(str);
exit(1);
}
int main(){
char line[MAXLINE];
FILE *fpin; if((fpin=popen("ls -l","r")) == NULL)
err_quit("popen error");
while(fgets(line,MAXLINE,fpin) != NULL){
if(fputs(line,stdout) ==EOF)
err_quit("fputs error");
}
if(ferror(fpin))
err_quit("fpin error");
if(pclose(fpin)==-1)
err_quit("pclose error");
return 0;
}

2.3 fifo

  • int mkfifo(const char *pathname,mode_t mode), 创建一个通信文件, 参数同open
  • mkfifo后, 以open打开文件pathname, 打开方式为只读或只写, 另外可以用阻塞或非阻塞方式打开
  • 以只读打开时, 函数会阻塞直到有进程以只写方式打开
  • 以只写打开时, 函数会阻塞直到有进程以只读方式打开
  • 可用于非父子进程通信, 不同的进程只需要将pathname设置为同一文件,就可以通信。双向通信时开需两个
  • 在一个进程中用mkfifo将一个文件设置为FIFO模式,同时open函数打开,read,Wright读写,另外一个进程只需要open和read,wright

 

三, 信号量

https://www.cnblogs.com/52php/p/5851570.html

3.1 信号量的工作原理

由于信号量只能进行两种操作等待和发送信号,即P(sv)和V(sv),他们的行为是这样的:

P(sv):如果sv的值大于零,就给它减1;如果它的值为零,就挂起该进程的执行

V(sv):如果有其他进程因等待sv而被挂起,就让它恢复运行,如果没有进程因等待sv而挂起,就给它加1.

举个例子,就是两个进程共享信号量sv,一旦其中一个进程执行了P(sv)操作,它将得到信号量,并可以进入临界区,使sv减1。而第二个进程将被阻止进入临界区,

因为当它试图执行P(sv)时,sv为0,它会被挂起以等待第一个进程离开临界区域并执行V(sv)释放信号量,这时第二个进程就可以恢复执行。

3.2、semget()函数

它的作用是创建一个新信号量或取得一个已有信号量,原型为:

int semget(key_t key, int num_sems, int sem_flags);

  key是整数值(唯一非零),不相关的进程可以通过它访问一个信号量,比如每个进程都调用:

  sem_id = semget((key_t) 1234, 1, 0666 | IPC_CREAT);就可以访问同一个信号量

3.3 semop()函数

它的作用是改变信号量的值,原型为:

  int semop(int sem_id, struct sembuf *sem_opa, size_t num_sem_ops);

四,共享内存

  参考:https://www.cnblogs.com/52php/p/5861372.html

4.1概念

  不同进程之间共享的内存通常安排为同一段物理内存。通常与信号量一起用。

4.2 函数

  int shmget(key_t key, size_t size, int shmflg);//不同的进程使用相同的key值,通常置为整形,就可以访问同一块共享内存

  void *shmat(int shm_id, const void *shm_addr, int shmflg);  // attach启动对该共享内存的访问,可以用memcpy直接操作空间

  int shmdt(const void *shmaddr);  //detach 该函数用于将共享内存从当前进程中分离。注意,将共享内存分离并不是删除它,只是使该共享内存对当前进程不再可用。

  int shmctl(int shm_id, int command, struct shmid_ds *buf);  //用来控制共享内存

五,消息队列

5.1 概念

  消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。 消息队列与命名管道一样,每个发送的数据块都有最大长度的限制。Linux用宏MSGMAX和MSGMNB来限制一条消息的最大长度和一个队列的最大长度。

5.2 函数

int msgget(key_t, key, int msgflg);//创建和访问消息队列

int msgsend(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg);//把消息添加到消息队列中

int msgrcv(int msgid, void *msg_ptr, size_t msg_st, long int msgtype, int msgflg);//从一个消息队列获取消息

int msgctl(int msgid, int command, struct msgid_ds *buf);//控制消息队列

六,socket

https://www.cnblogs.com/52php/p/5872596.html

6.1 概念

套接字的特性由3个属性确定,它们分别是:域、类型和协议。

套接字的域:

  AF_INET,它指的是Internet网络

  AF_UNIX表示UNIX文件系统,它就是文件输入/输出,而它的地址就是文件名。

套接字类型

  流套接字 SOCK_STREAM: TCP

  数据报套接字SOCK_DGRAM :UDP

6.2 套接字地址

  不同的域,有不同的套接字地址格式

  对于AF_UNIX域套接字来说,它的地址由结构sockaddr_un来描述,该结构定义在头文件sys/un.h中,它的定义如下:

1
2
3
4
struct sockaddr_un {  
    sa_family_t sun_family; // AF_UNIX,它是一个短整型  
    char        sum_path[]; // 路径名  
};

  对于AF_INET域套接字来说,它的地址结构由sockaddr_in来描述,它至少包括以下几个成员:

1
2
3
4
5
struct sockaddr_in {  
    short int            sin_family;//AF_INET  
    unsigned short int    sin_port;//端口号  
    struct in_addr        sin_addr;//IP地址  
};  

6.3 基于流套接字(tcp)的客户/服务器的工作流程

6.3.1 服务器

  socket-》bind-》listen-》accept

6.3.1 客户端

  socket-》connect

6.4 基于流套接字(tcp)的客户/服务器的工作流程

6.4.1 服务器

  socket-》bind-》recvfrom/sendto

6.4.1 客户端

  socket-》recvfrom/sendto

七,信号

https://www.cnblogs.com/52php/p/5813867.html

信号的名称是在头文件signal.h中定义的,信号都以SIG开头,常用的信号并不多,常用的信号如下:

更多的信号类型可查看附录表。

Unix/Linux进程间通信的更多相关文章

  1. Unix/Linux进程间通信(一):概述

    序 Linux下的进程通信手段基本上是从Unix平台上的进程通信手段继承而来的.而对Unix发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进 ...

  2. Unix/Linux进程间通信(二):匿名管道、有名管道 pipe()、mkfifo()

    1. 管道概述及相关API应用 1.1 管道相关的关键概念 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: 管道是半双工的,数据只能向一个方向流动:需要双方通信时,需要建立起两个管 ...

  3. UNIX/Linux进程间通信IPC---管道--全总结(实例入门)

    管道 一般,进程之间交换信息的方法只能是经由fork或exec传送打开文件,或者通过文件系统.而进程间相互通信还有其他技术——IPC(InterProcessCommunication) (因为不同的 ...

  4. Linux进程间通信(一): 信号 signal()、sigaction()

    一.什么是信号 用过Windows的我们都知道,当我们无法正常结束一个程序时,可以用任务管理器强制结束这个进程,但这其实是怎么实现的呢?同样的功能在Linux上是通过生成信号和捕获信号来实现的,运行中 ...

  5. Linux进程间通信(六):共享内存 shmget()、shmat()、shmdt()、shmctl()

    下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式 ...

  6. Linux进程间通信(七):消息队列 msgget()、msgsend()、msgrcv()、msgctl()

    下面来说说如何用不用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处.有关命名管道的更多内容可以参阅我的另一篇文章:Linux进程间通信 -- 使用命名管道 一.什么是消息队列 消息队列提 ...

  7. linux运维的认知及RHEL7 Unix/Linux 系统 介绍和安装

    如何成为一个优秀的linux运维人员?      如果你有机会和条件:环境能够磨练一个人的能力和意志.      大胆的做你从未做过的项目,每一个项目都是对自身的极大提升.      有好的环境资源不 ...

  8. Linux 进程间通信(一)

    Linux 进程间通信 进程是一个独立的资源分配单位,不同进程之间的资源是相互独立的,没有关联,不能在一个进程中直接访问另一个进程中的资源.但是,进程不是孤立的,不同的进程之间需要信息的交换以及状态的 ...

  9. linux进程间通信-概述

    一 进程间通信有如下的目的: 1.数据传输,一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M之间:2.共享数据,多个进程想要操作共享数据,一个进程对数据的修改,其他进程应该立刻看到 ...

随机推荐

  1. POJ-3233 Matrix Power Series 矩阵A^1+A^2+A^3...求和转化

    S(k)=A^1+A^2...+A^k. 保利求解就超时了,我们考虑一下当k为偶数的情况,A^1+A^2+A^3+A^4...+A^k,取其中前一半A^1+A^2...A^k/2,后一半提取公共矩阵A ...

  2. jQuery中防止表单提交两次的方法

    遇到过表单提交两次的情况,做个记录: 解决场景:首先是表单验证,其次是防止多次提交表单: jQuery中插件:validate_submitHandler_plugin,具体的可以使用关键字搜索: 使 ...

  3. 纪念L.A. Zadeh教授

    扎德教授永远活在我们心中 汪 培 庄 辽宁工程技术大学,智能工程与数学研究院,阜新,123000 摘要 全球科技工作者都在悼念扎德教授的逝世.本文对扎德创立模糊数学的历史意义,他与中国同仁的关系和影响 ...

  4. SQL Server-执行计划教会我如何创建索引

    先说点废话 以前有 DBA 在身边的时候,从来不曾考虑过数据库性能的问题,但是,当一个应用程序从头到脚都由自己完成,而且数据库面对的是接近百万的数据,看着一个页面加载速度像乌龟一样,自己心里真是有种挫 ...

  5. 用Apache Ant在Weka中嵌入新算法

    本文将介绍一种新的添加新的算法到Weka中的方法,国内的论坛基本都是通过IDE(Eclipse或NetBeans)编译,详细教程请见上一篇博客.经研究,发现国外的网站很流行用Ant这个方法,教程奉上. ...

  6. 基于JMH的Benchmark解决方案

    原始Benchmark做法 在设计新框架的时候,往往需要评估待接入的组件的性能,这个时候我们可能会利用UnitTest来进行,写一个方法,然后在循环里面跑,利用System.CurrentTimeMi ...

  7. 【问题】用ant编译时,提示编码utf为不可映射字符

    分析:eclipse默认的编码为gbk,而ant里的build.xml文件里定义的为utf-8格式.两者格式不统一. 建议:将工程的编码改成utf-8的格式,一般java工程也建议为utf-8格式.

  8. Python之路-函数

    一.函数是什么: python中函数定义:函数是逻辑结构化和过程化的一种编程方法.定义函数的方法为: def function(): ""The function definiti ...

  9. LeetCode 总结,二叉树各种类型问题小结

    三大遍历 前序遍历 中序遍历 后序遍历 关于三大基础遍历,必须要条件反射式的记住:三种遍历的迭代方式使用的都是栈,后序遍历必须使用了 两个栈,其余乱七八糟的解决方式统统就不要再记了. 广度遍历: 分析 ...

  10. keras 实现人工神经网络

    #encoding=utf-8 import numpy as np from keras.models import Sequential from keras.layers import Dens ...