管道是一种最基本的IPC机制,作用于父子进程之间,完成数据传递。
管道有以下特性:
1.其本质是一个伪文件(实为内核缓冲区)其本质是一个伪文件(实为内核缓冲区)
2.由两个文件描述符引用,一个表示读端,一个表示写端。
3.规定数据从管道的写端流入管道,从读端流出。
3.规定数据从管道的写端流入管道,从读端流出。
管道的原理: 管道实为内核使用环形队列机制,借助内核缓冲区(4k)实现。
无名管道的简单实现:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main()
{
int pipefd[2];
pid_t pid;
if (pipe(pipefd) == -1 )
{
printf("pipe() err..\n");
return -1;
}
pid = fork();
if (pid == -1)
{
printf("fork err..\n");
return -1;
}
if (pid == 0)
{
close(pipefd[0]);
write(pipefd[1], "hello hello....", 6);
close(pipefd[1]);
printf("child .....quit\n");
}
else if (pid > 0 )
{
int len = 0;
char buf[100] = {0};
close(pipefd[1]);
len = read(pipefd[0], buf, 100);
printf("len:%d, buf:%s \n", len , buf);
close(pipefd[0]);
}
wait(NULL);
printf("parent ..quit\n");
return 0;
}
命名管道也被称为FIFO文件,是一种特殊的文件。由于linux所有的事物都可以被视为文件,所以对命名管道的使用也就变得与文件操作非常统一。
有名管道实例
1.建立管道C语言实现 或者 shell指令 : mkfifo 文件名
C语言实现
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*
利用管道,两个进程间进行文件复制。
fifow
读文件1.txt
写入管道
fifor
读管道
写入2.txt文件
*/
int main(int argc, char *argv[])
{
//建立管道文件
int outfd = 0;
//打开管道文件,准备写数据
outfd = open("fifop", O_WRONLY | O_NONBLOCK);
//outfd = open("pp", O_WRONLY ); //阻塞模式
if (outfd == -1)
{
printf("infd open() err..\n");
exit(0);
}
return 0;
}
写端
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*
利用管道,两个进程间进行文件复制。
fifow
读文件1.txt
写入管道
fifor
读管道
写入2.txt文件
*/
int main(int argc, char *argv[])
{
//建立管道文件
mkfifo("fifop", 0644);
int infd;
//按只读方式 打开现有文件
infd = open("./1.txt", O_RDONLY);
if (infd == -1)
{
printf("infd open() err..\n");
exit(0);
}
int outfd;
//打开管道文件,准备写数据
//outfd = open("fifop", O_WRONLY | O_NONBLOCK);
outfd = open("fifop", O_WRONLY ); //阻塞模式
if (outfd == -1)
{
printf("infd open() err..\n");
exit(0);
}
char buf[1024];
int n = 0;
//从文件中读数据写入管道文件
while ( (n = read(infd, buf, 1024)) > 0)
{
write(outfd, buf, n);
}
close (infd);
close (outfd);
printf("fifow 写管道文件 success\n");
return 0;
}
读端
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
//打开2.txt 准备写数据
int outfd;
outfd = open("./2.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); //O_TRUNC 打开文件清空
if (outfd == -1)
{
printf("open() 2.txt err..\n");
exit(0);
}
//打开管道文件,准读数据
int infd;
infd = open("fifop", O_RDONLY);
if (infd == -1)
{
printf("open err ... \n");
exit(0);
}
char buf[1024];
int n = 0;
//从文件中读数据写入管道文件
while ( (n = read(infd, buf, 1024)) > 0)
{
write(outfd, buf, n);
}
printf("读管道文件是否失败。。。。\n");
close (infd);
close (outfd);
unlink("fifop");
printf("fifor 读管道文件 success\n");
return 0;
}
当没有数据可读时
O_NONBLOCK disable:read调用阻塞,即进程暂停执行,一直等到有数据来到为止。
O_NONBLOCK enable:read调用返回-1,errno值为EAGAIN。
当管道满的时候
O_NONBLOCK disable: write调用阻塞,直到有进程读走数据
O_NONBLOCK enable:调用返回-1,errno值为EAGAIN
如果所有管道写端对应的文件描述符被关闭,则read返回0
如果所有管道读端对应的文件描述符被关闭,则write操作会产生信号SIGPIPE
当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。
当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。