← 返回首页
Linux高级程序设计(四十八)
发表时间:2021-11-30 22:57:59
无名管道读写规律

1.无名管道读写规律

  1. 默认用read函数从管道读取数据是阻塞的。
  2. 调用write函数往管道写入数据,当缓冲区已满write函数也会阻塞。
  3. 通信过程中,读端口全部关闭后,写进程向管道写入数据时会收到(SIGPIPE)信号退出。

实例: 读写端都存在,只读不写。

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int argc, char *argv[])
{
    int fd_pipe[2];
    pid_t pid;

    if (pipe(fd_pipe) == -1)
    { // 创建无名管道
        perror("error to create pipe:");
    }

    //读写端都存在,只读不写。
    write(fd_pipe[1], "hello,world!", 12);
    char buff[128] = "";
    if (read(fd_pipe[0], buff, sizeof(buff)) == -1)
    {
        perror("error to read:");
        exit(1);
    }

    printf("buff=%s\n", buff);

    //再读一次,read函数阻塞
    if (read(fd_pipe[0], buff, sizeof(buff)) == -1)
    {
        perror("error to read:");
        exit(1);
    }
    printf("buff=%s\n", buff);
    return 0;
}

运行结果:

[root@iz2zefozq9h39txdb8s7npz shelldemo]# ./a.out
buff=hello,world!

实例: 读写端都存在,只写不读。默认缓冲区大小是64Kb。

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int argc, char *argv[])
{
    int fd_pipe[2];
    pid_t pid;

    if (pipe(fd_pipe) == -1)
    { // 创建无名管道
        perror("error to create pipe:");
    }

    //读写端都存在,只写不读。
    int num =0; 
    while(1){
       //每次写入1024个字节,1k字节。 
       if(write(fd_pipe[1],"hello,world!",1024)==-1){
          perror("error to write:");
          exit(1);
       }
       num++;  
       //缓冲区写满,也会发生阻塞。
       printf("num=%d\n", num);    
    }

    return 0;
}

运行结果:

[root@iz2zefozq9h39txdb8s7npz shelldemo]# ./a.out
num=1
num=2
num=3
num=4
num=5
num=6
num=7
num=8
num=9
num=10
num=11
num=12
num=13
num=14
num=15
num=16
num=17
num=18
num=19
num=20
num=21
num=22
num=23
num=24
num=25
num=26
num=27
num=28
num=29
num=30
num=31
num=32
num=33
num=34
num=35
num=36
num=37
num=38
num=39
num=40
num=41
num=42
num=43
num=44
num=45
num=46
num=47
num=48
num=49
num=50
num=51
num=52
num=53
num=54
num=55
num=56
num=57
num=58
num=59
num=60
num=61
num=62
num=63
num=64

实例: 只有读端,没有写端。

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int argc, char *argv[])
{
    int fd_pipe[2];
    pid_t pid;

    if (pipe(fd_pipe) == -1)
    { // 创建无名管道
        perror("error to create pipe:");
    }

    //先写一个字符串。
    write(fd_pipe[1], "hello,world!", 12);
    //关闭写端
    close(fd_pipe[1]);

    char buff[128] = "";
    int bytes=0;
    if ((bytes=read(fd_pipe[0], buff, sizeof(buff))) == -1)
    {
        perror("error to read:");
        exit(1);
    }

    printf("buff=%s\n", buff);
    printf("bytes=%d\n",bytes);
    //清除字符串内容
    memset(buff,0,sizeof(buff));
    //再读一次,read函数阻塞
    if ((bytes=read(fd_pipe[0], buff, sizeof(buff))) == -1)
    {
        perror("error to read:");
        exit(1);
    }
    printf("buff=%s\n", buff);
    printf("bytes=%d\n",bytes);
    return 0;
}

运行结果:

[root@iz2zefozq9h39txdb8s7npz shelldemo]# ./a.out
buff=hello,world!
bytes=12
buff=
bytes=0

实例: 只有写端,没有读端。

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int argc, char *argv[])
{
    int fd_pipe[2];
    pid_t pid;

    if (pipe(fd_pipe) == -1)
    { // 创建无名管道
        perror("error to create pipe:");
    }

    //关闭读端
    close(fd_pipe[0]);
    //读写端都存在,只写不读。
    int num =0; 
    while(1){
       //每次写入1024个字节,1k字节。 
       if(write(fd_pipe[1],"hello,world!",1024)==-1){
          perror("error to write:");
          exit(1);
       }
       num++;  
       //关闭读端后,写入进程会立刻收到SIGPIPE信号退出。
       printf("num=%d\n", num);    
    }
     return 0;
}

运行结果:

[root@iz2zefozq9h39txdb8s7npz shelldemo]# ./a.out
[root@iz2zefozq9h39txdb8s7npz shelldemo]# 

自定SIGPIPE的处理方式。

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>

void handler(int sig){
    if(sig==SIGPIPE){
        printf("管道破裂,立即退出....\n");
    }
}

int main(int argc, char *argv[])
{
    //自定义SIGPIPE信号处理方式
    signal(SIGPIPE,handler);

    int fd_pipe[2];
    pid_t pid;

    if (pipe(fd_pipe) == -1)
    { // 创建无名管道
        perror("error to create pipe:");
    }

    //关闭读端
    close(fd_pipe[0]);
    //读写端都存在,只写不读。
    int num =0; 
    while(1){
       //每次写入1024个字节,1k字节。 
       if(write(fd_pipe[1],"hello,world!",1024)==-1){
          perror("error to write:");
          exit(1);
       }
       num++;  
       //关闭读端后,写入进程会立刻收到SIGPIPE信号退出。
       printf("num=%d\n", num);    
    }

    return 0;
}

运行结果:

[root@iz2zefozq9h39txdb8s7npz shelldemo]# ./a.out
管道破裂,立即退出....
error to write:: Broken pipe