Linux进程间通信之管道

1,进程间通信 (IPC ) Inter-Process Communication

  比较好理解概念的就是进程间通信就是在不同进程之间传播或交换信息。

2,linux下IPC机制的分类:管道、信号、共享内存、消息队列、信号量、套接字

3,这篇主要说说管道:本质是文件,其他理论什么的网上已经有一大堆了,我就只写一点用法吧。

3.1 特点

     1)管道是最古老的IPC,但目前很少使用      2)以文件做交互的媒介,管道分为有名管道和无名管道      3)历史上的管道通常是指半双工管道

3.2 管道:有两种形式,命令行和非命令行

(1)命令行:

        mkfifo testfifo         echo "testfifo" >fifo         cat fifo

(2)非命令行:这里又分有名管道无名管道

编程模型:进程A创建管道(mkfifo) -> 进程A写打开管道(open) -> 进程B读打开管道(open) -> 进程A开始往管道里写数据(write) ->

       进程B从管道中读数据(read) -> 进程A关闭管道(close) -> 进程B关闭管道(close) -> 删除管道(unlink)

有名管道(实例):

进程A:

#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>

#define PIPENAME "pipetest"

int main()
{
    // 创建管道
    if(mkfifo(PIPENAME, 0666) < 0)
    {
        perror("mkfifo");
        return -1;
    }

    // 写打开管道 
    int fd = open(PIPENAME, O_WRONLY);
    if(-1 == fd)
    {
        perror("open");
        return -1;
    }

    unlink(PIPENAME);

    int i = 0;
    for(i = 0; i < 10; i++)
    {
        write(fd, &i, sizeof(i));
        printf("%d\n", i);
        sleep(1); // 这个是以秒为单位挂起
    }

    // 关闭管道
    close(fd);

    return 0;

}

进程B:

#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>

#define PIPENAME "pipetest"

int main()
{
    // 读打开管道
    int fd = open(PIPENAME, O_RDONLY);
    if(-1 == fd)
    {
        perror("open");
        return -1;
    }

    int num = 0;
    int i = 0;
    for(i = 0; i < 10; i++)
    {
        read(fd, &num, sizeof(int));
        printf("%d\n", num);
        fflush(stdout); // 强制刷新输出缓冲区
    }

    printf("\n");
    close(fd);

    return 0;

}

运行效果如下:

开另外一个终端,运行读进程

无名管道:适用于父子进程之间的通信      int pipe(int pipefd[2]):该函数在内核中创建管道文件,通过输出参数pipefd返回两个文件描述符,其中pipefd[0]用于读pipefd[1]用于写

注意:

  写数据的进程关闭读端pipefd[0]       读数据的进程关闭写端pipefd[1] 实例:

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdlib.h>

int main()
{
    int fd[2]; // 用来保存文件描述符
    pipe(fd);

    pid_t pid = fork();// 创建进程
    if(pid > 0)
    {
        // 父进程写管道,需要关闭读端
        close(fd[0]);
        int i = 0;
        for(i=10; i<20; i++)
        {
            write(fd[1], &i, sizeof(int));
            sleep(1);
        }

        close(fd[1]);// 关闭写端
        exit(0);
    }

    // 子进程读管道
    close(fd[1]); // 先关闭写端 
    int x;
    int i = 0;
    for(; i<10; i++)
    {
        read(fd[0], &x, sizeof(int));
        printf("%d ", x);
        setbuf(stdout, NULL);
    }
    close(fd[0]);
    printf("\n");

    return 0;
}

运行效果如下:

  比较好理解概念的就是进程间通信就是在不同进程之间传播或交换信息。

2,linux下IPC机制的分类:管道、信号、共享内存、消息队列、信号量、套接字

3,这篇主要说说管道:本质是文件,其他理论什么的网上已经有一大堆了,我就只写一点用法吧。

3.1 特点

     1)管道是最古老的IPC,但目前很少使用      2)以文件做交互的媒介,管道分为有名管道和无名管道      3)历史上的管道通常是指半双工管道

3.2 管道:有两种形式,命令行和非命令行

(1)命令行:

        mkfifo testfifo         echo "testfifo" >fifo         cat fifo

(2)非命令行:这里又分有名管道无名管道

编程模型:进程A创建管道(mkfifo) -> 进程A写打开管道(open) -> 进程B读打开管道(open) -> 进程A开始往管道里写数据(write) ->

       进程B从管道中读数据(read) -> 进程A关闭管道(close) -> 进程B关闭管道(close) -> 删除管道(unlink)

有名管道(实例):

进程A:

#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>

#define PIPENAME "pipetest"

int main()
{
    // 创建管道
    if(mkfifo(PIPENAME, 0666) < 0)
    {
        perror("mkfifo");
        return -1;
    }

    // 写打开管道 
    int fd = open(PIPENAME, O_WRONLY);
    if(-1 == fd)
    {
        perror("open");
        return -1;
    }

    unlink(PIPENAME);

    int i = 0;
    for(i = 0; i < 10; i++)
    {
        write(fd, &i, sizeof(i));
        printf("%d\n", i);
        sleep(1); // 这个是以秒为单位挂起
    }

    // 关闭管道
    close(fd);

    return 0;

}

进程B:

#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>

#define PIPENAME "pipetest"

int main()
{
    // 读打开管道
    int fd = open(PIPENAME, O_RDONLY);
    if(-1 == fd)
    {
        perror("open");
        return -1;
    }

    int num = 0;
    int i = 0;
    for(i = 0; i < 10; i++)
    {
        read(fd, &num, sizeof(int));
        printf("%d\n", num);
        fflush(stdout); // 强制刷新输出缓冲区
    }

    printf("\n");
    close(fd);

    return 0;

}

运行效果如下:

开另外一个终端,运行读进程

无名管道:适用于父子进程之间的通信      int pipe(int pipefd[2]):该函数在内核中创建管道文件,通过输出参数pipefd返回两个文件描述符,其中pipefd[0]用于读pipefd[1]用于写

注意:

  写数据的进程关闭读端pipefd[0]       读数据的进程关闭写端pipefd[1] 实例:

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdlib.h>

int main()
{
    int fd[2]; // 用来保存文件描述符
    pipe(fd);

    pid_t pid = fork();// 创建进程
    if(pid > 0)
    {
        // 父进程写管道,需要关闭读端
        close(fd[0]);
        int i = 0;
        for(i=10; i<20; i++)
        {
            write(fd[1], &i, sizeof(int));
            sleep(1);
        }

        close(fd[1]);// 关闭写端
        exit(0);
    }

    // 子进程读管道
    close(fd[1]); // 先关闭写端 
    int x;
    int i = 0;
    for(; i<10; i++)
    {
        read(fd[0], &x, sizeof(int));
        printf("%d ", x);
        setbuf(stdout, NULL);
    }
    close(fd[0]);
    printf("\n");

    return 0;
}

运行效果如下:

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏FreeBuf

Shodan新手入坑指南

*本文原创作者:xiaix,本文属FreeBuf原创奖励计划,未经许可禁止转载 亲们~黑五 Shodan Membership 只要5刀,你剁手了没? 什么是 ...

4895
来自专栏运维小白

10.23 linux任务计划cron

Linux任务计划 crontab -u、-e、-l、-r 格式:分 时 日 月 周 user command 文件/var/spool/cron/userna...

2009
来自专栏向治洪

Rest api简介

理解和使用内容协商 我们的开发者在发送一个 REST API 请求的同时,根据应用场景,针对相同的资源,可能会期待不同的返回形式。 比如,我希望根据用户客户端语...

2266
来自专栏用户2442861的专栏

Thrift 服务器端的几种工作模式分析

相关示例代码见:http://download.csdn.net/detail/hjx_1000/8374829

4942
来自专栏Java进阶架构师

手写实现一个迷你版的Tomcat

Tomcat,这只3脚猫,大学的时候就认识了,直到现在工作中,也常会和它打交道。这是一只神奇的猫,今天让我来抽象你,实现你!

1351
来自专栏信安之路

web应用渗透测试流程

对于web应用的渗透测试,一般分为三个阶段:信息收集、漏洞发现以及漏洞利用。下面我们就分别谈谈每个阶段需要做的事情。

1260
来自专栏北京马哥教育

运维架构师进阶:Linux进程管理

来源:IBM 译者:ljianhui 链接:blog.csdn.net/ljianhui/article/details/46718835 1.1 Linu...

3549
来自专栏左瞅瞅,右瞅瞅

nc命令详解

NetCat,在网络工具中有“瑞士军刀”美誉,其有Windows和Linux的版本。因为它短小精悍(1.84版本也不过25k,旧版本或缩减版甚至更小)、功能实用...

2431
来自专栏小巫技术博客

Android入门教程AS重制-A005 AS项目结构解析

上一节课给大家介绍了如何使用AS进行开发我们的第一个Android应用程序——HelloWorld,本节课来给大家系统介绍一下在Android Studio中A...

1023
来自专栏JavaEdge

操作系统之进程管理一、进程二、进程状态及状态转换三、进程队列四、进程控制五、深入理解六、线程七、死锁二、资源分配图(RAG:Resource Allocation Graph)三、死锁预防四、死锁避免

53810

扫码关注云+社区

领取腾讯云代金券