• 多进程间通信学习之无名管道


    • 无名管道:
    • 首先它是内核空间的实现机制;
    • 然后只能用于亲缘进程间通信
    • 它在内核所占的大小是64KB
    • 它采用半双工的通信方式;
    • 请勿使用lseek函数
    • 读写特点:
    • 若读端存在写管道,那么有多少数据,就写多少数据,直到无名管道写满为止,此时会出现写阻塞,当无名管道出现新的4KB空间,写操作就会解除阻塞;
    • 若读端不存在写管道,会出现管道破裂的情况;
    • 若写端存在读管道,那么有多少数据,就读多少数据,没有数据的时候,会出现阻塞等待
    • 若写端不存在读管道,有多少数据,就读多少,没有数据的时候,就会立即返回,即非阻塞的状态;
    • 创建无名管道(pipe函数):
    	#include 
    	
    	int pipe(int pipefd[2]);
    	/*
    	功能:
    	
    		创建一个管道,是一个单向的数据通道,可用于进程间通信
    	
    		数组pipefd返回两个指向管道的文件描述符:
    	
    			pipefd[0]指向管道的读端 
    			pipefd[1]指向管道的写端
    	
    		写入管道的数据被内核缓冲(64KB),直到从管道中读走
    	
    	参数:
    	
    		操作管道的文件描述符数组 
    	
    		pipefd[0]指向读端 pipefd[1] 指向管道的写端
    	
    	返回值:
    	
    		成功 0
    	
    		失败 -1 重置错误码
    	*/ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 实例要求:
    • 创建一个进程,要求使用无名管道,实现父进程写子进程读的操作;
    • 示例代码:
    	#include 
    	#include 
    	#include 
    	
    	#include 
    	#include 
    	
    	#include 
    	#include 
    	
    	int main(int argc, char const *argv[])
    	{   
    	    int pipe_fd[2] = {0};
    	    if(-1 == pipe(pipe_fd))
    	    {
    	        perror("pipe error");
    	        exit(-1);
    	    }
    	
    	    pid_t pid = 0;
    	    if(-1 == (pid = fork()))
    	    {
    	        perror("fork error");
    	        exit(-1);
    	    }
    	    else if(0 < pid) //父进程写
    	    {
    	        close(pipe_fd[0]);
    	        char buf[128] = {0};
    	        while(true)
    	        {
    	            fgets(buf,sizeof(buf),stdin);
    	            buf[strlen(buf) - 1] = '\0';
    	            write(pipe_fd[1],buf,sizeof(buf));
    	            if(!strncmp(buf,"quit",4))
    	            {
    	                exit(-1);
    	            }
    	        }
    	        sleep(2);
    	        wait(NULL);   //回收子进程的资源
    	
    	    }
    	    else if(0 == pid) //子进程读
    	    {
    	        close(pipe_fd[1]);
    	        char buf[128] = {0};
    	        while(true)
    	        {
    	            memset(buf,0,sizeof(buf));
    	            read(pipe_fd[0],buf,sizeof(buf));
    	            if(!strncmp(buf,"quit",4))
    	            {
    	                close(pipe_fd[0]);
    	                exit(-1);
    	            }
    	            printf("父进程发来的消息[%s]\n",buf);
    	        }
    	
    	    }
    	    
    	    return 0;
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 运行结果:
    	linux@ubuntu:~$ gcc pipe.c 
    	linux@ubuntu:~$ ./a.out 
    	hello beijing
    	父进程发来的消息[hello beijing]
    	i love china
    	父进程发来的消息[i love china]
    	quit
    	linux@ubuntu:~$ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 总结:
    • 为了防止误操作,在父进程和子进程里,分别关闭读端和写端;
  • 相关阅读:
    Windows 驱动开发 新手入门(四)
    Git常见场景命令总结
    「PAT乙级真题解析」Basic Level 1079 延迟的回文数 (问题分析+完整步骤+伪代码描述+提交通过代码)
    Java网络编程——BIO阻塞IO
    (十一)Powershell调用java实验
    驱动开发:内核远程堆分配与销毁
    【Android】Lombok for Android Studio 离线插件
    动态规划问题——LIS相关
    Springboot中使用线程池的三种方式
    docker
  • 原文地址:https://blog.csdn.net/qq_41878292/article/details/134095256