管道可以用来在两个进程之间传递数据,如: ps -ef | grep “bash”, 其中‘|’就是管道,其作用就是将 ps 命令的结果写入管道文件,然后 grep 再从管道文件中读出该数据进行过滤。
你可以用管道操作符I来连接进程。Linux与MS-DOS不同,在Linux下通过管道连接的进程可以同时运行,并且随着数据流在它们之间的传递可以自动地进行协调。举一个简单的例子,你可以使用sort命令对ps命令的输出进行排序。
$ ps >psout.txt
$ sort psout.txt >pssort.out
一个更精巧的解决方案是用管道来连接进程,如下:
$ ps | sort>passort.out
如果想在屏幕上分页显示输出结果,可以再连接第三个进程more,将它们都放在同一个命令行,如下:
$ ps|sort|more
允许连接的进程数目是没有限制的。假设你想看看系统中运行的所有进程的名字,但不包括shell本身,可以使用下面的命令:
$ ps -xo comm |sort |uniq |grep -v sh |more
这个命令首先按字母顺序排序ps命令的输出,再用uniq命令去除名字相同的进程,然后用grep -v
sh命令删除名为sh的进程,最终将结果分页显示在屏幕上。与使用一系列单独的命令并且每个命令都带有自己的临时文件相比,这是一个更精巧的解决方案。但这里有一点 需要引起注意:如果你有一系列的命 令需要执行,相应的输出文件是在这组命令被创建的同时立刻被创建或写入的,所以决不要在命令流中重复使用相同的文件名。如果尝试执行以下命令:
cat mydata.txt |sort |uniq > mydata.txt
最终将得到一个空文件,因为你在读取文件mydata. txt之前就已经覆盖了这个文件的内容。
有名管道可以在任意两个进程之间通信
有名管道的创建:
◼ 命令创建: mkfifo FIFO
◼ 系统调用创建
#include
#include
-int mkfifo( const char *filename, mode_t mode);
//filename 是管道名 mode 是创建的文件访问权限
-代码演示:
write.c写端:
#include
#include
#include
#include
#include
#include
int main()
{
int fd = open("FIFO", O_WRONLY);
assert(fd != -1);
printf("open FIFO success\n");
while(1)
{
printf("please input: ");
char buff[128] = {0};
fgets(buff, 128, stdin);
write(fd, buff, strlen(buff) - 1);
if(strncmp(buff, "end", 3) == 0)
{
break;
}
}
close(fd);
exit(0);
}
read.c读端:
#include
#include
#include
#include
#include
#include
int main()
{
int fd = open("FIFO", O_RDONLY);
assert(fd != -1);
printf("open FIFO success\n");
while(1)
{
char buff[128] = {0};
int n = read(fd, buff, 127);
if(n <= 0 || 0 == strncmp(buff, "end", 3))
{
break;
}
printf("%s\n", buff);
}
close(fd);
exit(0);
#include
/*
pipe()成功返回 0,失败返回-1
fds[0]是管道读端的描述符
fds[1]是管道写端的描述符
*/
int pipe( int fds[2]);
代码演示:
#include
#include
#include
#include
#include
int main()
{
int fd[2];
int res = pipe(fd);
assert( res != -1 );
pid_t pid = fork();
assert( pid != -1 );
if( pid == 0 )
{
char buff[128] = {0};
read(fd[0], buff, 127);
printf("child read: %s\n", buff);
}
else
{
write(fd[1], "hello", 5);
}
close(fd[0]);
close(fd[1]);
exit(0);
}
3、 管道的特点
◼ 无论有名还是无名,写入管道的数据都在内存中
◼ 管道是一种半双工通信方式(通信方式有单工、半双工、全双工)
◼ 有名和无名管道的区别:有名可以在任意进程间使用,而无名主要在父子进程间
管道的实现: