linux Dup2 网络转发,Linux系统编程:dup2()重定向

对于Dup2 的理解:

源代码:

1 #include

2 #include

3 #include

4 #include

5 #include

6

7 #define MSGSIZE 20

8 #define READ 0

9 #define WRITE 1

10

11 int main(int argc, char const *argv[])12 {13 int p[2], bytes, res, c;14 char inbuf[10240];15 intpid;16 printf("%c", 11);17 if(pipe(p) == -1){//creat the pipe , if pipe is built failed , exit .

18 perror("pip call");19 exit(1);20 }21 pid =fork();22 if(pid != 0){//creat parent pid and child pid.

23 close(p[READ]);//close parent pipe read

24 dup2(p[WRITE], 1);25 close(p[WRITE]);//close parent pipe write

26 execlp(argv[1], argv[1], NULL);27 }28 else{29

30 close(p[WRITE]);//close child pipe write

31

32 dup2(p[READ],0);33

34 close(p[READ]);//close child pipe read

35

36 execlp(argv[2], argv[2], NULL);37 }38 return 0;39 }

通过命令行输出:

./a.out “ls” “ps”

仅仅在终端执行了ps的命令, 而没有看到ls 命令的结果。

因此,开始走入了第一个误区:父进程没有执行

通过调试 在父进程执行if条件中加入以下代码:

if(pid != 0){

printf("4556\n");

close(p[READ]);

dup2(p[WRITE], 1);

close(p[WRITE]);

printf("4556\n");

execlp(argv[1], argv[1], NULL);

}

加入了2个printf , 但是只有dup2 上面的printf 结果输出到屏幕上,因此我注释了 dup2(p[WRITE], 1); 结果在父进程if语句中的dup2 后面的命令都执行并且输出到屏幕上了。通过查找dup2 命令发现了重定向的强大之处。

先解释下dup2 命令,

int dup2(int filedes, int filedes2);

说明:

用dup2 则可以用filedes2 参数指定新描述符的数值。如果filedes2 已经打开,则先将其关闭。如若filedes 等于filedes2,则返回filedes2,而不关闭它。

dup2(p[WRITE], 1); 这句话可以理解为将标准输出重定向到p[WRITE], 因此在这句话后面的所有printf 语句打印或者exec 执行的内容都输入到了p[WRITE]中。刚开始有个迷惑,就是既然已经close(1)了,为什么还能输入到p[WRITE]中,通过自己的直觉判断,应当是close(1)关闭了屏幕的输出,但是它有缓冲区保存printf打印出的内容,并且由于重定向的关系,输进了p[WRITE]中。

代码:

1 #include

2 #include

3 #include

4 #include

5 #include

6

7 #define MSGSIZE 20

8 #define READ 0

9 #define WRITE 1

10

11 int main(int argc, char const *argv[])12 {13 int p[2], bytes, res, c;14 char inbuf[10240];15 intpid;16 printf("%c", 11);17 if(pipe(p) == -1){//creat the pipe , if pipe is built failed , exit .

18 perror("pip call");19 exit(1);20 }21 pid =fork();22 if(pid != 0){//creat parent pid and child pid.

23 close(p[READ]);//close parent pipe read

24 dup2(p[WRITE], 1);25 close(p[WRITE]);//close parent pipe write

26 printf("123!\n");27 execlp(argv[1], argv[1], NULL);28 perror("execlp");//error output

29 }30 else{31 while(1){32 res = read(p[READ], inbuf, 10240);33 if(res>0)34 printf("%s\n", inbuf);35 break;36 }37

38 close(p[WRITE]);//close child pipe write

39

40 dup2(p[READ],0);41

42 close(p[READ]);//close child pipe read

43

44 execlp(argv[2], argv[2], NULL);45 }46 return 0;47 }

通过在子进程中用while(1)循环读取p[READ]内容,发现读出了父进程本应在屏幕上打印的内容,因此父进程是执行了所有命令行,只是通过重定向命令存到了p[WRITE]管道中。

由于有dup2(p[READ], 0) 命令,因此猜测标准输入的文件描述符定向到了p[READ] , 因此如果猜测没错,通过getchar()读取文件标准输入并把P[READ]的内容输出到屏幕上则证明我猜想没错。

代码:

1 #include

2 #include

3 #include

4 #include

5 #include

6

7 #define MSGSIZE 20

8 #define READ 0

9 #define WRITE 1

10

11 int main(int argc, char const *argv[])12 {13 int p[2], bytes, res, c;14 char inbuf[10240];15 intpid;16 printf("%c", 11);17 if(pipe(p) == -1){//creat the pipe , if pipe is built failed , exit .

18 perror("pip call");19 exit(1);20 }21 pid =fork();22 if(pid != 0){//creat parent pid and child pid.

23 close(p[READ]);//close parent pipe read

24 dup2(p[WRITE], 1);25 close(p[WRITE]);//close parent pipe write

26 printf("123!\n");27 execlp(argv[1], argv[1], NULL);28 perror("execlp");//error output

29 }30 else{31 //while(1){32 //res = read(p[READ], inbuf, 10240);33 //if(res>0)34 //printf("%s\n", inbuf);35 //break;36 //}

37

38 close(p[WRITE]);//close child pipe write

39

40 dup2(p[READ],0);41 while((c=getchar()) != -1){42 printf("%c", c);43 }44 close(p[READ]);//close child pipe read

45

46 execlp(argv[2], argv[2], NULL);47 }48 return 0;49 }

通过在dup2(p[READ], 0) 后面while循环读入输入流输入的字符并且打印出来, 发现结果果然是p[READ]的内容,猜疑没错。

为了更清楚的理解dup2的重定向含义,想理解dup2(fd,0)和dup2(0,fd)功能相同吗?

为了得到答案,找些资料发现,答案是不同。

测试代码:

1 #include

2 #include

3 #include

4

5 #define BUFMAXSIZE 4096

6

7 int main(int argc, char *argv[])8 {9 intfd;10 intn;11 charbuf[BUFMAXSIZE];12 intfs;13 fs = open("test", O_RDWR);14 if((fd = open("duan", O_RDWR )) == -1)15 {16 perror("open error!");17 return(1);18 }19

20 dup2(fd, 1); //dup2(0,fd);

21

22 while((n = read(fs, buf, BUFMAXSIZE)) > 0)23 {24 printf("begin to read...\n");25 if(write(STDOUT_FILENO, buf, n) !=n)26 {27 perror("write error!");28 return(1);29 }30 printf("end to write...\n");31 }32 if(n < 0)33 {34 perror("read error");35 return(1);36 }37

38 return 0;39 }

dup(fd, 0) 这段代码测试, 打印出了duan 文件里面的内容。

之后创建个文件Levi 里面写和duan 文件不同的内容。

通过./a. out < Levi输出:

第一个输出是dup(fd, 0) 输出了Duan 文件的内容。即是fd的内容

第二个输出是dup(0, fd) 输出了Levi 文件的内容。即是 通过文件重定向到标准输入的内容。

从图中的输出结果已经可以看到两者的区别了。

第一种dup2(fd,0)之前已经将fd 初始化指向到文本Duan了,

并且不会被后面的代码所修改。

第二种dup2(0,fd)则将fd 重新指向到文件描述符0所代表的文件(即终端标准输入)了。

那么可以看到,程序的执行中不会再读取Duan 文件了。

而是进入了一种交互模式。

另外,这时“输入重定向”也可以生效了。

文件描述符0被 “

所以,这里直接输出了该文本的内容。

dup2(fd,0) 相当于“输入重定向”的功能,

dup2(0,fd) 不是表示fd 所指的文件接收来自终端的输入,因为,fd 已经不再指向原来的那个文件了。

它和文件描述符0 已经在共享同一个文件表项(即指向终端标准输入的那个表项)了。

“输出重定向”的功能可以用dup2(fd ,1) 替代。

dup2(fd,1) 和dup2(1,fd) 也是大同小异。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值