Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1902809
  • 博文数量: 217
  • 博客积分: 4362
  • 博客等级: 上校
  • 技术积分: 4180
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-20 09:31
文章分类

全部博文(217)

文章存档

2017年(1)

2015年(2)

2014年(2)

2013年(6)

2012年(42)

2011年(119)

2010年(28)

2009年(17)

分类: C/C++

2011-07-14 11:01:46

    在我的“通过管道和重定向实现linux管道命令”当中实现cat file | sort命令,没有使用标准I/O函数库中提供的popen()函数和pclose()函数,在本文中,我们一起探讨一下通过这两个标准的I/O函数来实现上述这个命令。
    先看一下这两个函数的定义吧:

FILE * popen(const char *command, const char *type);

    popen()函数用来创建一个管道并启动另外一个进程,新启动的进程要么从该管道当中读出标准输入(输入重定向),要么向该管道写入标准输出(输出重定向)。
    具体的第二个参数type表示I/O模式的类型。如果command命令的输出作为其他命令的输入(输出重定向),type为“r”权限;如果command命令的输入为其他命令的输出(输入重定向),type为“w”权限。

int pclose(FILE *stream);

    这个函数用来关闭由popen()创建的标准I/O流,等待其中的命令终止,然后返回给shll的终止状态。
    在我们对"cat file | sort"程序进行修改之前,先看一个简单的程序:
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <stdlib.h>

  4. #define MAXLINE 80

  5. int main()
  6. {
  7.     FILE *fp;
  8.     char buf[MAXLINE], command[MAXLINE];
  9.     int n;
  10.     
  11.     n = fgets(buf, MAXLINE, stdin);
  12.     n = strlen(buf);
  13.     if(buf[n-1] == '\n') {
  14.         n--;
  15.     }
  16. /*有关snprintf()函数的是有,具体可查阅printf()函数族的使用*/
  17.     snprintf(command, sizeof(command), "head %s", buf);
  18.     fp = popen(command, "r");
  19.     while(fgets(buf, MAXLINE, fp) != NULL) {
  20.         fputs(buf, stdout);
  21.     }
  22.     pclose(fp);
  23.     return 0;
  24. }
执行结果如下:
  1. ^_^[sunny@sunny-laptop ~/summer]47$ ./a.out
  2. file            //file是我的输入,下面都是file文件当中的内容
  3. dsf
  4. abcde
  5. 92381
  6. 8232
  7. sadf
  8. 872
  9. 1988
  10. 2000
  11. 1022
  12. 2012
  13. ^_^[sunny@sunny-laptop ~/summer]48$

    程序说明:在调用popen()函数,就是创建了一个新的进程,同时创建了一个管道,注意,type的类型为“r”说明这里是输出重定向,也就是将command的输出作为其他命令的输入,写到创建的管道当中,并不是将其执行的结果输出到标准输出上。下来的话,通过对fp流的读取操作,读取管道当中command的输出结果,为了查
看结果是不是正确的,我们将其显示在了标准输出。
    下面实现"cat file | sort"命令:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <fcntl.h>

  7. #define MAXLEN 80
  8. #define MAX 1024

  9. int main()
  10. {
  11.     FILE *fpin, *fpout;
  12.     char command1[MAXLEN]={0}, command2[MAXLEN]={0}, buff[MAX]={0};

  13.     snprintf(command1, sizeof("cat file"), "cat file");
  14.     snprintf(command2, sizeof("sort"), "sort");
  15.     fpin = popen(command1, "r"); //输出重定向
  16.     fpout = popen(command2, "w"); //输入重定向

  17.     while(read(fileno(fpin), buff, MAX) != 0) {
  18.         write(fileno(fpout), buff, MAX);
  19.     }
  20. /*
  21.  *或者这个while循环可以用这个while循环来代替
  22.  *
  23.     while(fgets(buff, MAX, fpin) != NULL) {
  24.         fputs(buff, fpout);
  25.     }
  26. */
  27.     pclose(fpin);
  28.     pclose(fpout);
  29.     return 0;
  30. }
    这个程序的执行结果是:
  1. ^_^[sunny@sunny-laptop ~/summer]84$ ./a.out

  2. 1022
  3. 1988
  4. 2000
  5. 2012
  6. 8232
  7. 872
  8. 92381
  9. abcde
  10. dsf
  11. fan
  12. sadf
  13. ^_^[sunny@sunny-laptop ~/summer]85$
    程序说明:首先使用snprintf()函数将两个通过管道要执行的命令分别存放在command1和command2当中,然后调用popen函数两次,第一个是所谓的输出重定向,将cat file的结果输入到popen()创建的管道当中,第二个是所谓的输入重定向,将管道当中的数据作为sort命令的输入。之后,通过一个while()循环,读取第一个管道当中的数据到buff变量当中,然后把buff变量当中的数据输入到第二个管道当中,作为sort命令的输入。
    小结:在这次实现这个命令的时候,是创建了两个管道,之前的话,只有创建了一个管道就可以实现,但是如果要通过这两个标准的I/O函数来实现的话,我目前没有想到只创建一个管道就来实现的方法。



阅读(3579) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~