Linux命名管道特性总结

Linux命名管道特性总结

话不多说,直接总结命名管道的特性吧!
1.必须同时有读端和写端。假如只有一边,那么open()函数将会阻塞。
2.打开管道时,必须有读的一端和写的一端,否则打开的open()会阻塞。
3.在写入时,如果没有读端,写入方将会受到SIGPIPE信号。
4.默认情况下,读取是阻塞的,写入是非阻塞的。
下面用代码实测:

#include <head.h>

int kill(pid_t,int);
void sigHandler2(int no)
{
    printf("[%d] receive signal %d\n",getpid(),no);
}

int main(int argc ,char **argv)
{
    if(argc != 2){
        printf("Usage :%s fifo name\n",argv[0]);
        exit(1);
    }
	int i=0;
    
    for ( ; i < 1; i++)
    {
        pid_t pid =fork();
        if(pid == 0){
            break;
        }
    }
    if(i == 1){
        int fifo = open (argv[1],O_RDWR);
        if(fifo == -1){
            perror(" open error ");
            exit(1);
        }
        printf("[%d],fifo fd =%d\n",getpid(),fifo);
        char buf[1024];
        int len = 0;
        while (1)
        {
            memset(buf,0,sizeof(buf));
            len = read(fifo,buf,1024);
            printf("father:afte open\n");
            if(len <0){
                perror(" read error");
                exit(1);
            }
            printf("%c\n",buf[0]);
#if 0
            close(fifo);
            while(1);
#endif
        }
    }
    else{
        signal(SIGPIPE,sigHandler2);
        printf("before open\n");
        int fifo = open (argv[1],O_WRONLY);
        printf("son:afte open\n");
        if(fifo == -1){
            perror(" open error ");
            exit(1);
        }
        printf("[%d],fifo fd =%d\n",getpid(),fifo);
        int x='A';
        for (  ;;)
        {
            write(fifo,&x,4);
            ++x;
            sleep(1);
        }
    }
	return 0;
}

首先测试1,注释掉父进程的打开fifo的代码,原来是 int fifo = open (argv[1],O_RDWR);
改成int fifo =0;
然后运行,得到的结果是
user@ubuntu18:~/Music$ ./named_fifo fifo1
[55849],fifo fd =0
son before open
之后就是光标一直闪烁,无任何输出了,没有后面的"son:afte open\n",这就说明,只有一端打开管道,会导致打开阻塞。
测试性质2
把父进程的打开时的参数改成O_WRONLY,也就是两边都已只写的方式打开,这也会导致open阻塞。
测试结果同上。
测试3
把父进程里买呢的#if 0 改为#if 1 ,也是说,父进程读1次之后就把管道关闭了。测试结果如下:
user@ubuntu18:~/Music$ ./named_fifo fifo1
[60454],fifo fd =3
son before open
son:afte open
[60455],fifo fd =3
father:afte open
A
[60455] receive signal 13
[60455] receive signal 13
[60455] receive signal 13
[60455] receive signal 13
[60455] receive signal 13
从测试结果可以看出,子进程在父进程关闭读端之后,再次向管道写入数据,会收到SIGPIPE的信号,man page 对于SIGPIPE的说明如下:
SIGPIPE 13 Term Broken pipe: write to pipe with no readers;
简单翻译就是在没有读端的情况下向管道写数据将会收到此信号。
测试4
修改父子进程的逻辑如下

if(i == 1){
        int fifo =0;
        fifo = open (argv[1],O_RDWR);
        if(fifo == -1){
            perror(" open error ");
            exit(1);
        }
        printf("[%d],fifo fd =%d\n",getpid(),fifo);
        char buf[1024];
        int len = 0;
        while(1);
#if 0
        while (1)
        {
            memset(buf,0,sizeof(buf));
            len = read(fifo,buf,1024);
            printf("father:afte open\n");
            if(len <0){
                perror(" read error");
                exit(1);
            }
            printf("%c\n",buf[0]);

        
#endif
        //}
    }
    else{
        signal(SIGPIPE,sigHandler2);
        printf("son before open\n");
        int fifo = open (argv[1],O_WRONLY);
        printf("son:afte open\n");
        if(fifo == -1){
            perror(" open error ");
            exit(1);
        }
        printf("[%d],fifo fd =%d\n",getpid(),fifo);
        int x='A';
        for (  ;;)
        {
            int len= 0;
            printf("son before write\n");
            len = write(fifo,&x,4);
            printf("son after write,len =%d\n",len);
            ++x;
            sleep(1);
        }
    }

得到如下的测试结果:
user@ubuntu18:~/Music$ ./named_fifo fifo1
[63688],fifo fd =3
son before open
son:afte open
[63689],fifo fd =3
son before write
son after write,len =4
son before write
son after write,len =4
son before write
son after write,len =4
son before write
父进程里面是打开管道后什么也不做,子进程一直在向管道里面写数据,写的过程没有阻塞。
可以看出,在管道写满之前,write函数不会被阻塞。
修改关键代码如下:

if(i == 1){
        int fifo =0;
        fifo = open (argv[1],O_RDWR);
        if(fifo == -1){
            perror(" open error ");
            exit(1);
        }
        char buf[1024];
        int len = 0;
#if 1
        while (1)
        {
            memset(buf,0,sizeof(buf));
            printf("father before read\n");
            len = read(fifo,buf,1024);
            printf("father:afte read\n");
            if(len <0){
                perror(" read error");
                exit(1);
            }
            printf("%c\n",buf[0]);
#endif
        }
    }
    else{
        signal(SIGPIPE,sigHandler2);
        int fifo = open (argv[1],O_WRONLY);
        if(fifo == -1){
            perror(" open error ");
            exit(1);
        }
        int x='A';
        for (int k=0  ;k<1;k++)
        {
            int len= 0;
            len = write(fifo,&x,4);
            ++x;
            sleep(1);
        }
        while(1);
    }

上述的改动就是让子进程只向管道写一次数据。父进程一直从管道读取数据。
得到以下的测试结果:
user@ubuntu18:~/Music$ ./named_fifo fifo1
father before read
father:afte read
A
father before read

可以看出,在管道没有数据时,从管道的读操作将会引起阻塞。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值