无名管道只能用于有亲缘进程之间的通信,有名管道可以实现无亲缘关系的通信。
有名管道 fifo 给文件系统提供一个路径,这个路径和管道关联,只要知道这个管道路径,
就可以进行文件访问,fifo 是指先进先出,也就是先写入的数据,先读出来。
特点:
a、有名字,储存于普通文件系统中
b、任何具有相应权限的进程都可以使用open()来获取FIFO的文件描述符
c、跟普通文件一样,用read()和writ()来读和写
d、不能用lseek来定位
e、支持多写入者同时进行写操作而数据不会相互践踏
mkfifo 的用法
int mkfifo(const char *pathname, mode_t mode);
参数*pathname:路径名,管道名称。
参数 mode:管道的权限。
返回值:成功返回 0,错误返回-1。
无名管道例程:
1、create.c(创建无名管道,创建源文档)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void filecopy(FILE *ifp,char *buff);
int main(void)
{
char buff[]="Everything that kills me makes me feel alive!\n";
long int times = 100000;
char *file1 = "/home/test/fifotest/date.txt";
FILE *fp1;
if((fp1 = fopen(file1,"a+")) == NULL)
{
printf("can't open the file %s\n",file1);
exit(1);
}
printf("Wrinting is begin\n");
while(times--)
filecopy(fp1,buff);
fclose(fp1);
printf("Wrinting is over\n");
return 0;
}
void filecopy(FILE *ifp,char *buff)
{
int i,j;
j = 0;
i = strlen(buff)-1;
while(i--)
{
putc(buff[j],ifp);
j++;
}
putc('\n',ifp);
}
2、writefifo.c(写入有名管道)
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
#include <stdlib.h>
void main()
{
const char* fifo_name = "/home/topeet/test/fifotest/fifo_exchange";
char *file1 = "/home/topeet/test/fifotest/data.txt";
int pipe_fd = -1;
int data_fd = -1;
int bytes_read = 0;
int bytes_sent = 0;
int res_read = -1;
int res_sent = -1;
int res = -1;
char buffer[PIPE_BUF+1];
if(access(fifo_name,F_OK) == -1)
{
res = mkfifo(fifo_name,0777);
if(res != 0)
{
fprintf(stderr,"Could not create fifo %s\n",fifo_name);
exit(EXIT_FAILURE);
}
}
printf("Process %d opening FIFO O_WRONLY\n",getpid());
pipe_fd = open(fifo_name,O_WRONLY);
data_fd = open(file1,O_RDONLY);
printf("Process %d result %d,data_fd of file is %d\n", getpid(), pipe_fd,data_fd);
//从数据文件读取数据
if(pipe_fd != -1)
{
res_read = 0;
res_read = read(data_fd,buffer,PIPE_BUF);
buffer[res_read] = '\0';
bytes_read += res_read;
//第一次读取成功,写入FIFO文件
while(res_read>0)
{
res_sent = write(pipe_fd,buffer,res_read);
if(res_sent == -1)
{
fprintf(stderr, "Write error on pipe\n");
exit(EXIT_FAILURE);
}
bytes_sent += res_sent;
res_read = read(data_fd,buffer,PIPE_BUF);
buffer[res_read] = '\0';
bytes_read += res_read;
}
fprintf(stderr, "%d bytes of data were read in all,%d bytes of data were write in all\n",bytes_read,bytes_sent);
close(pipe_fd);
close(data_fd);
//关闭文件
}
else
exit(EXIT_FAILURE);
printf("Process %d finished\n", getpid());
exit(EXIT_SUCCESS);
//退出程序
}
3、readfifo.c(从有名管道读出)
#include<stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
int main()
{
const char *fifo_name = "/home/test/fifotest/fifo_exchange";
char *write_file = "/home/test/fifotest/write.txt";
int pipe_fd = -1;
int write_fd = -1;
int bytes_read = 0;
int bytes_write = 0;
int res_read = 0;
int res_write = 0;
char buffer[PIPE_BUF+1];
//清空缓冲数组
memset(buffer, '\0', sizeof(buffer));
printf("Process %d opening FIFO O_RDONLY\n", getpid());
//以只读方式打开FIFO文件
pipe_fd = open(fifo_name,O_RDONLY);
//以只写方式创建保存数据的文件
write_fd = open(write_file,O_WRONLY|O_CREAT, 0644);
if(pipe_fd == -1)
{
printf("Opened the fifo file failure!\n");
exit(1);
}
if(write_fd == -1)
{
printf("Created the write file failure!\n");
exit(1);
}
printf("Process %d result %d,write_fd of file is %d\n", getpid(), pipe_fd,write_fd);
//读取FIFO文件中数据,并保存至Dateformfifo文件中
do
{
res_read = read(pipe_fd,buffer,PIPE_BUF);
res_write = write(write_fd,buffer,res_read);
if(res_write == -1)
{
printf("Read file failed\n");
exit(1);
}
bytes_read += res_read;
bytes_write += res_write;
}
while(res_read>0);
printf("Process %d finished\n", getpid());
close(pipe_fd);
close(write_fd);
printf("%d bytes of data were read in all,%d bytes of data were write in all\n",bytes_read,bytes_write);
exit(0);
}
编译运行测试
使用gcc命令对create.c、writefifo.c、readfifo.c文件进行编译,ls查看。
使用 ./create命令,创建文本文件。如图,多了data.txt文件。
vim data.txt查看文本文件内容。
使用**./writefifo &**命令,生成有名管道。ls查看如图。
使用**./readfifo命令从管道内读取数据转存。使用ls**查看。
查看write.txt文件内容。