zoukankan      html  css  js  c++  java
  • Linux进程间通信-管道

    Linux进程通信系列文章将详细介绍各种通信方式的机制和区别

    1.进程间通信

    每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程A把数据从用户空间拷到内核缓冲区,进程B再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信。

    2、进程间通信方式

    一、进程间通信-管道

    二、进程间通信-命名管道

    三、进程间通信-消息队列

    四、进程间通信-共享内存

    3、进程间通信-管道(pipe)

     3.1 管道是如何通信的  

    (1)父进程创建管道,得到两个⽂件描述符指向管道的两端

    (2)父进程fork出子进程,⼦进程也有两个⽂件描述符指向同⼀管道。

    (3)父进程关闭fd[0],子进程关闭fd[1],即⽗进程关闭管道读端,⼦进程关闭管道写端(因为管道只支持单向通信)。⽗进程可以往管道⾥写,⼦进程可以从管道⾥读,管道是⽤环形队列实现的,数据从写端流⼊从读端流出,这样就实现了进程间通信。 

    3.2 利用管道实现通信

    #include "stdio.h"
    #include "unistd.h"
    #include "string.h"
    
    int main(int argc, char* argv[])
    {
        int fd[2];
        int ret = pipe(fd);
        if (ret == -1)
        {
            perror("pipe error
    ");
            return 1;
        }
    
        pid_t pid = fork();
        if (pid == 0)   // child
        {
            close(fd[0]);
            int i = 0;
            char* msg = "i am child
    ";
            while (i < 5)
            {
                write(fd[1],msg,strlen(msg));
                sleep(2);
                i++;
            }
    
        }
        else if(pid > 0)
        {
            close(fd[1]);
            char buf[256] = {0};
            int j = 0;
            while (j < 5)
            {
                int n = read(fd[0],buf,256);
                if (n>0)  
                {  
                    buf[n] = '';  
                }  
                printf("%s",buf);
                j++;  
            }
        }
        else
        {
            perror("fork error
    ");
            return 1;
        }
        return 0;
    }

    运行结果:

     3.3 管道读取数据的四种的情况

    (1)读端不读,写端一直写

    (2)写端不写,读端一直读

    (3)读端一直读,写端关闭

    (4)写端一直写,读端关闭

    #include "stdio.h"
    #include "unistd.h"
    #include "string.h"
    #include "sys/wait.h"
    #include "sys/types.h"
    
    int main(int argc, char* argv[])
    {
        int fd[2];
        int status = 0;
        int ret = pipe(fd);
        if (ret == -1)
        {
            perror("pipe error
    ");
            return 1;
        }
    
        pid_t pid = fork();
        if (pid == 0)   // child
        {
            close(fd[0]);
            int i = 0;
            char* msg = "i am child
    ";
            while (i < 10)
            {
                write(fd[1],msg,strlen(msg));
                sleep(1);
                i++;
            }
    
        }
        else if(pid > 0)
        {
            close(fd[1]);
            char buf[256] = {0};
            int j = 0;
            while (j < 5)
            {
                int n = read(fd[0],buf,256);
                if (n>0)  
                {  
                    buf[n] = '';  
                }  
                printf("%s",buf);
                j++;  
            }
            close(fd[0]);
            ret = waitpid(pid,&status,0);
            printf("exit single(%d),exit(%d)
    ", status & 0xff, (status >> 8) & 0xff);  
        }
        else
        {
            perror("fork error
    ");
            return 1;
        }
        return 0;
    }

    运行结果:

    使用kill -l 查看13号信号,可以知道13号信号代表SIGPIPE。

    4、管道的特点

    (1)管道只允许具有血缘关系的进程间通信,如父子进程间的通信。

    (2)管道只允许单向通信。

    (3)管道内部保证同步机制,从而保证访问数据的一致性。

    5、管道的容量

    测试管道容量大小只需要将写端一直写,读端不读且不关闭fd[0],即可。

    #include "stdio.h"
    #include "unistd.h"
    #include "string.h"
    #include "sys/wait.h"
    #include "sys/types.h"
    
    int main(int argc, char* argv[])
    {
        int fd[2];
        int status = 0;
        int ret = pipe(fd);
        if (ret == -1)
        {
            perror("pipe error
    ");
            return 1;
        }
    
        pid_t pid = fork();
        if (pid == 0)   // child
        {
            close(fd[0]);
            int i = 1;
            while (i)
            {
                write(fd[1],"A",1);
                printf("pipe capacity: %d
    ",i++);
            }
            close(fd[1]);
    
        }
        else if(pid > 0)
        {
            close(fd[1]);
            waitpid(pid,NULL,0);
            close(fd[0]);
        }
        else
        {
            perror("fork error
    ");
            return 1;
        }
        return 0;
    }

    运行结果:

    由此可见,管道大小为64k

  • 相关阅读:
    字符串转输入流、输入流转字符串
    base64编码与解码
    PHP AES/ECB 128加密
    JQ下拉加载更多
    php记录代码执行时间
    PHP SOAP 提交XML
    AES 加密 PHP 和 JAVA 互通
    PHP RSA算法 HMAC-SHA1加密算法
    php SHA256Hex加密
    php UTF8 转字节数组,后使用 MD5 计算摘要
  • 原文地址:https://www.cnblogs.com/alvin2010/p/8597980.html
Copyright © 2011-2022 走看看