使用FIFO来进行两个进程间的通信

时间:2022-06-16 14:01:26

使用命名管道的操作和使用普通的文本文件类似,都是系统调用open函数去打开创建好的管道,使用read,write函数操作,操作完成后用close函数关闭。

从FIFO中读取数据的规则是:

1,如果一个进程为了从fifo中读取数据而阻塞打开fifo,n那么称该进程内的读操作为设置了阻塞标志的读操作。

         2,如果有进程写打开了fifo,而且当前fifo内没有数据,则对于这于设置了阻塞标志的读操作来说,将一直阻塞,对于没有设置阻塞标志读操作来说则返回-1,当前errno值为EGIN,提醒以后再试。

3,对于设置阻塞标志的读操作来说,造成阻塞的原因有两种:① 当前fifo内有数据,但有其他的进程在读这些数据。②fifo里面没有数据。解阻塞的原因则是fifo有新的数据写入不管新写入数据量的大小,也不论读操作请求多少数据。

4,读打开的阻塞标志只对本进程第一个读操作施加作用,如果本进程内有多个读操作序列,则在第一个读操作被唤醒并完成读操作后,其他要执行的读操作将不再阻塞。即使在执行读操作时,fifo里面没有数据也一样(读操作返回0)。

5,如果没有写进程打开fifo,则设置了阻塞标志的读操作也会阻塞。

向fifo中写入数据的规则是:

1.如果一个进程为了向fifo中写数据而阻塞打开fifo,那么称该进程内的写操作为设置了阻塞标志的写操作。

2.对于设置了阻塞标志的写操作,当要写入的数据量不大于PIPE_BUF时,Linux将保证写入的原子性,如果此时管道空闲缓冲区不足以容纳要写入的数据时,则进入睡眠,知道当缓冲区能够容下要写入数据字节数时,才开始进行一次性写操作。

3.当要写入的数据量大于PIPE_BUF时,linux不能保证写入的原子性,在写满fifo空闲缓冲区后,写操作返回。

4.要写入的数据量不大于PIPE_BUF时,linux将保证写入原子性,如果当前缓冲区能容下要写的数据,则写完后返回,相反的话,返回EAGIN错误,提醒以后再写。

write_fifo.c:

#include<sys/types.h>
#include<sys/stat.h>
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<limits.h>
#include<stdlib.h>
#include<time.h>
#define BUFES PIPE_BUF
int main(void)
{
    int fd;
    int n,i;
    char buf[BUFES];
    time_t tp;
    printf("%d\n",getpid());
   if((fd=open("fifo1",O_WRONLY))<0)
    {
        printf("open failed\n");
        exit(1);
    }
   for(i=0;i<10;i++)
    {
        time(&tp);
        n=sprintf(buf,"write fifo %d sends %s",getpid(),ctime(&tp));
        printf("send msg:%s\n",buf);
        if((write(fd,buf,n+1))<0)
        {
            printf("write failed!\n");
            close(fd);
            exit(1);
        }
        sleep(3);
    }
    close(fd);
    exit(0);
}

read_fifo.c

#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<limits.h>
#include<fcntl.h>
#define BUFES PIPE_BUF
int main(void)
{
    int fd;
    int len;
    char buf[BUFES];
    mode_t mode =0666;
    if((fd=open("fifo1",O_RDONLY))<0)
    {
        printf("Open failed");
        exit(1);
    }
    while((len=read(fd,buf,BUFES))>0)
    {
        printf("Read_fifo read:%s\n",buf);
    }
    close(fd);
    exit(0);
    return 0;
}

Step 1:     lishun@lishun-Qt:~$ mkfifo -m 0666 fifo1   (建立管道)

Step2:     gcc write_fifo.c -o write

Ste2:       ./write     (write 当前 阻塞,一直到运行read)

Step3:     gcc read_fifo.c -o read

Step4:     ./read