前言

   进程是一个独立的资源管理单元,不同进程间的资源是独立的,不能在一个进程中访问另一个进程的用户空间和内存空间。但是,进程不是孤立的,不同进程之间需要信息的交互和状态的传递,因此需要进程间数据的传递、同步和异步的机制。

    当然,这些机制不能由哪一个进程进行直接管理,只能由操作系统来完成其管理和维护,Linux提供了大量的进程间通信机制,包括同一个主机下的不同进程和网络主机间的进程通信,如下图所示:

  • 同主机间的信息交互
  • 无名管道

    特点:多用于亲缘关系进程间通信,方向为单向;为阻塞读写;通信进程双方退出后自动消失

    问题:多进程用同一管道通信容易造成交叉读写的问题
  • 有名管道

    FIFO(First In First Out),方向为单向(双向需两个FIFO),以磁盘文件的方式存在;通信双方一方不存在则阻塞
  • 消息队列

    可用于同主机任意多进程的通信,但其可存放的数据有限,应用于少量的数据传递
  • 共享内存

    可实现同主机任意进程间大量数据的通信,但多进程对共享内存的访问存在着竞争
  • 同主机进程间同步机制:信号量(Semaphore)
  • 同主机进程间异步机制:信号(Signal)
  • 网络主机间数据交互:Socket(套接字)

1. 无名管道

1). 概念

    无名管道是一类特殊的文件,在内核中对应着一段特殊的内存空间,内核在这段内存空间中以循环队列的方式存储数据;

   无名管道的内核资源在通信双方退出后自动消失,无需人为回收;

   无名管道主要用于连通亲缘进程(父子进程),用于双方的快捷通信,通信为单向通信

2). 操作

1. 创建

pipe()

  • 头文件

        #include <unistd.h>
  • 函数原型

        int pipe(int pipedes[2])
  • 参数

pipedes[2]:存储文件描述符

  • 返回值

    成功:0

    失败:-1

2. 读写

读进程 写进程 管道无数据 管道有数据
阻塞√ 立刻返回0 返回数据
阻塞√ 读阻塞 读数据并返回
阻塞√ 收到SIGPIPE信号,write返回-1
阻塞√ 写入 若满,阻塞等待

3. 重定向

  所谓重定向,即关闭某个标准I/O设备(stdin(0), stdout(1), stderr(2)), 而将某一个普通的文件描述符设置为0/1/2.

  重定向,主要是采用 dup函数来实现的:

  • dup函数

  • 作用

    复制文件描述符

  • 头文件

        #include <unistd.h>
  • 函数原型

    函数 原型 描述
    dup int dup(int oldfd) 复制oldfd文件表项,并返回未用的最小值描述符
    dup2 int dup2(int oldfd, int newfd) 复制oldfd文件表项到newfd,newfd为用户自定义值,而后关闭oldfd
  • 参数

oldfd:源文件的描述符(要求该文件描述符必须有效,文件必须处于打开状态)

newfd:新的文件描述符,个人理解为oldfd的软链接

  • 返回值

    成功:最小值文件描述符(dup) / newfd的值(dup2)

    失败:-1

2. 有名管道

1). 概念

 又称FIFO(Fisrt In First out), 是磁盘上的一个特殊文件,没有在磁盘存储真正的信息,其所存储的信息在内存中

 通信双方进程结束后,自动丢弃FIFO中的信息,但其在磁盘的文件路径本身依然存在

2). 操作

1. 创建 - mkfifo()

  • 头文件

        #include <sys/stat.h>
  • 函数原型

        int mkfifo(const char *pathname, mode_t mode)
  • 参数

pathname: FIFO文件

mode: 创建文件的属性(权限)

  • 返回值

    成功:0

    失败:-1

2. 读写

读进程 写进程 FIFO无数据 FIFO有数据
阻塞 阻塞
阻塞 阻塞
写入 读出(未满,读写同时)
√x 即写中途退出,读直接返回0 same
√x 读中途退出,写返回SIGPIPE same

3. 补充

access函数

  • 作用

    检查用户(进程)对文件的权限

  • 头文件

        #include <unistd.h>
  • 函数原型

        int access(const char *pathname, int mode)
  • 参数

pathname: 即文件名

mode:测试的属性

mode description
F_OK 该文件是否存在
R_OK 可读
W_OK 可写
X_OK 可执行
bitwise 属性(读/写/执行等)
  • 返回值

    成功:0

    失败:-1

4. 代码示例

1). PIPE

/*
* Filename: pipe.c
*/ #include <stdio.h>
#include <unistd.h> //for pipe()
#include <string.h> //for memset()
#include <stdlib.h> //for exit() int main()
{
int fd[2];
char buf[20];
if(-1 == pipe(fd))
{
perror("pipe");
exit(EXIT_FAILURE);
} write(fd[1], "hello,world", 12);
memset(buf, '\0', sizeof(buf)); read(fd[0], buf, 12);
printf("The message is: %s\n", buf); return 0;
}

2). FIFO

程序的步骤:

  1. 创建一个新的fifo文件
  2. fifo_snd.c文件负责向fifo中写入数据
  3. fifo_rcv.c负责从fifo中读取数据并打印

1. fifo_snd.c:

/*
*File: fifo_send.c
*/ #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <fcntl.h> #define FIFO "/tmp/my_fifo" int main()
{
char buf[] = "hello,world"; //`. check the fifo file existed or not
int ret;
ret = access(FIFO, F_OK);
if(ret == 0) //file /tmp/my_fifo existed
{
system("rm -rf /tmp/my_fifo");
} //2. creat a fifo file
if(-1 == mkfifo(FIFO, 0766))
{
perror("mkfifo");
exit(EXIT_FAILURE);
} //3.Open the fifo file
int fifo_fd;
fifo_fd = open(FIFO, O_WRONLY);
if(-1 == fifo_fd)
{
perror("open");
exit(EXIT_FAILURE); } //4. write the fifo file
int num = 0;
num = write(fifo_fd, buf, sizeof(buf));
if(num < sizeof(buf))
{
perror("write");
exit(EXIT_FAILURE);
} printf("write the message ok!\n"); close(fifo_fd); return 0;
}

2. fifo_rcv.c:

/*
*File: fifo_rcv.c
*/ #include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <fcntl.h> #define FIFO "/tmp/my_fifo" int main()
{
char buf[20] ;
memset(buf, '\0', sizeof(buf)); //`. check the fifo file existed or not
int ret;
ret = access(FIFO, F_OK);
if(ret != 0) //file /tmp/my_fifo existed
{
fprintf(stderr, "FIFO %s does not existed", FIFO);
exit(EXIT_FAILURE);
} //2.Open the fifo file
int fifo_fd;
fifo_fd = open(FIFO, O_RDONLY);
if(-1 == fifo_fd)
{
perror("open");
exit(EXIT_FAILURE); } //4. read the fifo file
int num = 0;
num = read(fifo_fd, buf, sizeof(buf)); printf("Read %d words: %s\n", num, buf); close(fifo_fd); return 0;
}

Linux进程间通信 -- 管道(pipe)的更多相关文章

  1. Linux进程间通信—管道

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

  2. Linux进程间通信:管道,信号量,消息队列,信号,共享内存,套接字

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

  3. linux中管道(pipe)一谈

    /*********************************************** 管道(pipe)是Linux上进程间通信的一种方式,其是半双工(数据流只能在一个方向上流动(还需要经过 ...

  4. Linux进程间通信-管道深入理解(转)

    原文地址:https://www.linuxidc.com/Linux/2018-04/151680.htm Linux进程通信系列文章将详细介绍各种通信方式的机制和区别 1.进程间通信 每个进程各自 ...

  5. Linux进程间通信---管道和有名管道

    一.管道 管道:管道是一种半双工的通信方式,数据只能单方向流动,而且只能在具有亲缘关系的进程间使用,因为管道 传递数据的单向性,管道又称为半双工管道.进程的亲缘关系通常是指父子进程关系. 管道的特点决 ...

  6. 详解linux进程间通信-管道 popen函数 dup2函数

    前言:进程之间交换信息的唯一方法是经由f o r k或e x e c传送打开文件,或通过文件系统.本章将说明进程之间相互通信的其他技术-I P C(InterProcess Communication ...

  7. linux 进程间通信之pipe

    在实际开发过程中,程序员必须让拥有依赖关系的进程集协调,这样才能达到进程的共同目标.  每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内 ...

  8. Linux 进程间通信(管道、共享内存、消息队列、信号量)

           进程通信 : 不同进程之间传播或交换信息    为什么要进程通信呢? 协同运行,项目模块化 通信原理 : 给多个进程提供一个都能访问到的缓冲区. 根据使用场景,我们能划分为以下几种通信 ...

  9. linux进程间通信-管道

    一 管道的局限性 管道有两个局限性:(1)他是半双工(即数据只能在一个方向上流动).(2)它只能在具有公共祖先的进程之间使用.一个管道由一个进程创建,然后该 进程调用fork,此后父子进程之间就可该管 ...

随机推荐

  1. vim 安装vim-javascript插件--Vundle管理

    最近看了一下node.js,但是写的时候,vim对js没有很好的提示.于是就安装插件来处理,准备安装vim-javascript.但是安装github上面的插件时,推荐用Vundle和pathogen ...

  2. C#开发微信小程序

    个人见解,欢迎交流,不喜勿喷.   微信小程序相比于微信公众号的开发,区别在于微信小程序只请求第三方的数据,整个界面的交互(view)还是在微信小程序上实现,前后端完全分离,说白了,微信小程序开发与具 ...

  3. asp.net—策略模式

    一.什么是策略模式 定义:定义一系列算法,把一个个算法封装成独立类并实现同一个接口,使得它们之间可以相互替换. 二.怎么使用策略模式 首先模拟一个场景:有一个用户想买车.  可以有多种方式买车: (1 ...

  4. NetCore入门篇:(四)Net Core项目启动文件Startup

    一.Startup介绍 1.Startup文件是Net Core应用程的启动程序,实现全局配置. 2.Net Core默认情况下,静态文件及Session都未启动,需要在Startup文件配置启动,否 ...

  5. 利用MVC5+EF6搭建博客系统

    https://www.cnblogs.com/wyt007/p/7880137.html

  6. FTP 作业整理

    一.FTP 客户端 与服务器端(没有解决黏包问题的代码) 服务器端设置 import socket import json ADDR = () sk =socket.socket() sk.bind( ...

  7. Java基础学习篇---------多态

    一.多态性的理解 1.向上转型:子类为父类对象实例化,调用的一定是子类覆写的方法,他们之间找的是共性 2.向下转型:子类扩充了父类的某些功能,而父类中没有该功能,他们之间找的是特性 案例: Numbe ...

  8. 二,windows下安装memcached服务

    window下安装memcached服务的流程如下: 1. 下载memcache的windows稳定版,解压放某个盘下面,比如在c:\memcached 2. 在终端(也即cmd命令界面)下输入 ‘c ...

  9. mysql导入数据错误

    ERROR 29 (HY000): File '/tmp/cun' not found (Errcode: 13) # sudo /etc/init.d/apparmor reload(重新加载) 大 ...

  10. ReentrantReadWriteLock源码分析(一)

    此处源码分析,主要是基于读锁,非公平机制,JDK1.8. 问题: 1.ReentrantReadWriteLock是如何创建读锁与写锁? 2.读锁与写锁的区别是什么? 3.锁的重入次数与获取锁的线程数 ...