这里写自定义目录标题
- 基本概念
- 管道特征
- 编写模型
- 有名管道模型
- 示例demo
- write.c
- read.c
 
- 结果
 
- 无名管道
 
基本概念
进程间存在天然的壁垒,进程间通信(Interperocess Communication,IPC)是指二个或者多个进程之间进行数据交换的过程
管道特征
管道是进程间通讯的一种常用方法。管道分为有名管道fifo和无名管道pipe
- 管道创建后是单向的,一端是写,一端是读(如果需要想双向,没办法创建二根管道)
- 管道有大小,linux内核对每个管道的大小限制在4096字节
- 无名管道一般用在父子线程间通讯
- 有名管道一般用在进程和不同线程之间通讯
- 管道是阻塞的,读取管道过程中一直处于阻塞的状态
- 管道在被读取前,只能写入一次,多次写入是无效的
编写模型
有名管道模型
| 步骤 | 进程A | 进程B | 步骤 | 
|---|---|---|---|
| 1.创建管道 | mkfifo | ||
| 2.打开管道 | open | open | 1.打开管道 | 
| 3.读写管道 | write/read | write/read | 2.读写管道 | 
| 4.关闭管道 | close | close | 3.关闭管道 | 
| 5.删除管道 | unlink | 
示例demo
注意:有名管道需要依靠文件来传递,我们再/tmp目录下去建文件,因为tmp目录是临时目录,开机就清除了
write.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#define FIFO_FILE "/tmp/fifo"
int main(void){
    printf("创建管道...\n");
    if(mkfifo(FIFO_FILE,0666) == -1){
        perror("mkfifo");
        return -1;    
    }
    
    printf("打开管道...\n");
    int fd = open(FIFO_FILE,O_WRONLY);
    if(fd == -1){
        perror("open");
        return -1;
    }
    
    printf("发送数据...\n");
    for(;;){
        printf(">");
        char buf[1024];
        gets(buf);
        if(!strcmp(buf,"!"))
            break;
        if(write(fd,buf,(strlen(buf)+1)))  * sizeof(buf[0]) == -1){
            perror("write");
            return -1;        
        }                     
    }
    
    printf("关闭管道...\n");
    if(close(fd) == -1){
        perror("close");
        return -1;    
    }
    
    printf("删除管道...\n");
    if(unlink(FIFO_FILE) == -1){
        perror("unlink");
        return -1;    
    }
    
    printf("大功告成!\n");
    return 0;
}
read.c
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#define FIFO_FILE "/tmp/fifo"
int main(void){
    printf("打开管道...\n");
    int fd = open (FIFO_FILE,O_RDONLY);
    if(fd == -1){
        perror("open");
        return -1;
    }
    
    printf("接收数据...\n");
    for(;;){
        char buf[1024];
        size_t rb = read(fd,buf,sizeof(buf));
        if(rb == -1){
            perror("read");
            return -1;
        }    
        
        if(!rb)
            break;
        printf("< %s\n",buf);
    }
    
    printf("关闭管道...\n");
    if(close(fd) == -1){
        perror("close");
        return -1;
    }
    
    printf("大功告成!\n");
    return 0;
结果
我们先编译一下
 
 生成write 和read二个可执行文件
 
我们测试一下管道
 最后删除了管道,不然创建的时候会有一些莫名错误!
无名管道
这个比较简单直接上代码
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void){
    printf("父进程:创建管道...\n");
    int pipefd[2];
    
    if(pipe(pipefd) == -1){
        perror("pipe");
        return -1;    
    }
    
    printf("父进程:创建进程...\n");
    pid_t pid = fork();
    if(pid == -1){
        perror("fork");
        return -2;    
    }
    
    /* fork之后就多了一个子进程,父进程和子进程在宏观
    上是并发的关系,这样就理解为2个mian函数一起运行了
    之后我们用if判断语句来做分支处理,这样实现pipe的
    通讯*/
    
    
    if(pid == 0){
        printf("子进程:关闭写端...\n");
        close(pipefd[1]);
        printf("子进程:接收数据...\n");
        for(;;){
            char buf[1024];
            ssize_t rb = read(pipefd[0],buf,sizeof(buf));
            if(rb == -1){
                perror("read");
                return -1;            
            }
            else if(rb == 0){
                //注意:如果读到的返回结果是0,说明pipe被关闭了,这个时候结束
                break;            
            } 
            
            puts(buf);  //数据打印出来            
        }
        printf("子进程:关闭读端...\n");
        close(pipefd[0]);
        printf("子进程:大功告成!\n");
    }
    
    printf("父进程:关闭读端...\n");
    close(pipefd[0]);
    printf("父进程:发送数据...\n");
    for(;;){
        char buf[1024];
        if(!strcmp(buf,"!")) {
            break;        
        }   
        
        if(write(pipefd[1],buf,strlen(buf)+1) == -1){
            perror("write");
            return -1;        
        }
    }
    printf("父进程:关闭写端...\n");
    close(pipefd[1]);
    if(wait(0) == -1){
        perror("wait");
        return -1;    
    }
    
    printf("父进程:大功告成!\n");
    return 0;
}



















