管道/FIFO

Posted it8343

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了管道/FIFO相关的知识,希望对你有一定的参考价值。

管道:

 1 #include<stdio.h>
 2 #include<unistd.h>
 3 #include<stdlib.h>
 4 #include<string.h>
 5 #include<wait.h>
 6 
 7 /*管道没有名字,只能用于有亲缘关系的进程间通信*/
 8 
 9 typedef struct stu
10 {
11     int id;
12     char name[20];
13 }Stu;
14 
15 int main()
16 {
17     int pfd[2];
18     int ret=pipe(pfd);//创建管道(管道只能在父进程中创建)
19 
20     if(ret<0)
21         perror("pipe");//判断是否创建成功
22 
23     int pid=fork();//创建子进程
24     if (pid<0)
25         perror("fork");
26 
27     else if(pid>0)//父进程写文件
28     {
29         close(pfd[0]);//关闭读文件描述符
30         Stu s[5];
31         int i;
32         for(i=0;i<5;i++)
33         {
34             printf("id=");
35             scanf("%d",&s[i].id);getchar();
36             printf("name=");
37             scanf("%s",s[i].name);getchar();
38         }
39             write(pfd[1],s,5*sizeof(Stu));//写文件,放入s数组
40             printf("id	name
");
41 
42         close(pfd[1]);//关闭写文件
43         waitpid(pid,NULL,0);//等待子进程结束
44         return 0;
45     }
46 
47 
48     else if(pid==0)//子进程读文件
49     {
50         close(pfd[1]);//关闭写文件标识符
51         int i;
52         Stu s2[5];
53         while(1)
54         {
55             ret=read(pfd[0],s2,5*sizeof(Stu));//读取文件放入s2数组
56             if(ret<0)//判断读取是否成功
57             {
58                 perror("read");
59             }
60             if(ret==0)//判断是否读取完毕
61             {
62                 printf("read over
");
63                 exit(0);
64             }
65 
66             else//输出读取文件
67             {
68                 for(i=0;i<5;i++)
69                 printf("%d	%s
",s2[i].id,s2[i].name);
70                 i++;
71             }
72         }
73         close(pfd[0]);//关闭读文件
74         return 0;
75     }
76 }

运行结果:

id=1001    //---------------------------输入(写文件)
name=aaa
id=1002
name=bbb
id=1003
name=ccc
id=1004
name=ddd
id=1005
name=eee//---------------------------输出(读文件)
id    name
1001    aaa
1002    bbb
1003    ccc
1004    ddd
1005    eee
read over

FIFO(有名管道):

代码1:写文件程序

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
typedef struct stu
{
    int id;
    char name[20];
}Stu;

void fun(int sig)
{
    printf("中断..
");
    return;
}

int main()
{
    int fd;
    int ret;
    char buf[1024];
    signal(SIGPIPE,fun);//给一个已经关闭的终端发送信息会产生13信号

    //创建管道
    ret = mkfifo("file_f",0777);
    if(ret<0)
    {
        if(errno != EEXIST)//判断创建是否出错(除去已经创建错误)
        {
            perror("mkfifo");
            return -1;
        }
    }
    printf("mkfifo success.
");

    //打开管道
    printf("open ..
");
    fd = open("file_f",O_WRONLY);//只写方式打开
    printf("open fd = %d
",fd);
    if(fd<0)
    {
        printf("open error.
");
    }



    //写操作

    Stu s[100];int i;
    //while(1)
    printf("input the len
");//输入创建多少个数据
    int len;
    scanf("%d",&len);
    for(i=0;i<len;i++)
    {
        printf("id=");

        scanf("%d",&s[i].id);getchar();
        printf("name=");
        scanf("%s",s[i].name);getchar();
    }

        ret = write(fd,s,len*sizeof(struct stu) );//写入到数组中
        if(ret<0)
        {
            printf("write error.
");
            goto END;
        }

    printf("write success.
");

END:
    close(fd);
    return 0;
}

 

代码2:读文件程序:

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>

typedef struct stu 
{
    int id; 
    char name[20];
}Stu;

int main()
{
    int fd; 
    int ret;
    //创建 
    ret = mkfifo("file_f",0777);
    if(ret<0)
    {   
        if(errno!=17)
        {
            perror("mkfifo");
            return -1; 
        }
    }   
    printf("mkfifo success.
");

    //打开管道
    printf("open ..
");
    fd = open("file_f",O_RDONLY);
    printf("open fd = %d
",fd);
    if(fd<0)
    {   
        printf("open error.
");
    }   
    printf("id	name
");
    
    printf("in put the len
");
    int len;
    scanf("%d",&len);//输入要读取几个数据

    Stu s[100];int i;
        ret = read(fd,s,sizeof(Stu)*len);
    for(i=0;i<len;i++)
    {   
        if(ret<0)
        {
            printf("read error.
");
            goto END;
        }
        if(ret == 0)
        {
            printf("pipe broken.
");
            goto END;
        }
        if(s[i].id==0)// 一旦数据读取完毕就退出
        {
            goto END;
        }
        printf("%d	%s
",s[i].id,s[i].name);//打印读取到的数据
    }   
END:
    printf("read success
");
    close(fd);
    return 0;
}

运行结果:右边输入,左边输出

技术分享图片

 

另一种FIFO(边读边写)

代码1:

 1 #include <sys/types.h>
 2 #include <sys/stat.h>
 3 #include <stdio.h>
 4 #include <stdlib.h>
 5 #include <errno.h>
 6 #include <unistd.h>
 7 #include <fcntl.h>
 8 #include <string.h>
 9 #include <signal.h>
10 
11 
12 void fun(int sig)
13 {
14     printf("中断..
");
15     return;
16 }
17 
18 int main()
19 {
20     int fd;
21     int ret;
22     char buf[1024];
23 
24 
25     signal(SIGPIPE,fun);
26     //创建 
27     ret = mkfifo("file_f",0777);
28     if(ret<0)
29     {
30         if(errno != EEXIST)
31         {
32             perror("mkfifo");
33             return -1;
34         }
35     }
36     printf("mkfifo success.
");
37 
38     //打开管道
39     printf("open ..
");
40     fd = open("file_f",O_WRONLY);
41     printf("open fd = %d
",fd);
42     if(fd<0)
43     {
44         printf("open error.
");
45     }
46 
47     //写操作
48     while(1)
49     {
50 
51         fgets(buf,1024,stdin);//输入
52 
53         ret = write(fd,buf,strlen(buf)+1 );
54         if(ret<0)
55         {
56             printf("write error.
");
57             goto END;
58         }
59     }
60     printf("write success.
");
61 
62 END:
63     close(fd);
64     return 0;
65 }

代码2:

 1 #include <sys/types.h>
 2 #include <sys/stat.h>
 3 #include <stdio.h>
 4 #include <stdlib.h>
 5 #include <errno.h>
 6 #include <unistd.h>
 7 #include <fcntl.h>
 8 
 9 int main()
10 {
11     int fd; 
12     int ret;
13     char buf[1024];
14 
15     //创建 
16     ret = mkfifo("file_f",0777);
17     if(ret<0)
18     {   
19         if(errno != EEXIST)
20         {
21             perror("mkfifo");
22             return -1; 
23         }
24     }   
25     printf("mkfifo success.
");
26 
27     //打开管道
28     printf("open ..
");
29     fd = open("file_f",O_RDONLY);
30     printf("open fd = %d
",fd);
31     if(fd<0)
32     {   
33         printf("open error.
");
34     }   
35 
36     while(1)
37     {   
38         ret = read(fd,buf,1024);//读取输出
39         if(ret<0)
40         {
41             printf("read error.
");
42             goto END;
43         }
44         if(ret == 0)
45         {
46             printf("pipe broken.
");
47             goto END;
48         }
49         printf("read buf:%s
",buf);
50     }   
51 END:
52     close(fd);
53     return 0;
54 }

输出结果:

技术分享图片

以上是关于管道/FIFO的主要内容,如果未能解决你的问题,请参考以下文章

Python 子进程挂起命名管道

FIFO管道返回0而不是正确的整数?

Python 从命名管道/FIFO 中读取 JSON

读取管道后的bash返回码

Linux系统编程——进程间通信:命名管道(FIFO)

多处理是不是支持命名管道(FIFO)?