19重定向管道与popen模型

重定向 dup2

int dup(int fd)

重定向文件描述符  int newFd = dup(STDOUT_FILENO)

newFd 指向 stdout

int dup2(int fd1, int fd2)

重定向文件描述符  dup2(newFd, STDOUT_FILENO)

stdout 指向 newFd

重定向输入输出到管道

例子1: 父进程标准输入后,有子进程进行标准输出

void testDup()

{

      int fds[2];

      pid_t pid;

      char buf[128];

      if(pipe(fds))

      {

           printf("file:%s,line:%d",__FILE__,__LINE__);

           perror("fail pipe!");

           return ;

      }

      pid=fork();

      if(pid<0)

      {

           printf("file:%s,line:%d",__FILE__,__LINE__);

           perror("fail fork!");

           return ;

      }

      else if(pid==0)

      {

           close(fds[1]);

           //直接输出

           dup2(STDOUT_FILENO,fds[0]);  

      }

      else

      {

           close(fds[0]);

           dup2(STDIN_FILENO,fds[1]);

           //父进程接受键盘输入

           while(1)

           {

           fprintf(stderr,"parent send:");

           memset(buf,0,sizeof(buf));

           read(STDIN_FILENO,buf,sizeof(buf));

           write(fds[1],buf,strlen(buf));

           }

           close(fds[1]);

      }

      return ;

}

例子2: ls | more 类似实现

思路:

1.ls 的输出,是输出到  STDOUT

2.more 的输入,是从 STDIN 接受

3.我们要实现 ls 的输出,作为 more 的输入

4.所以我们要创建管道,然后,把 STDOUT 和 STDIN 重定向到管道

5.这样 我们就实现了: 连接 ls 和 more

void testDup2()

{

      int fds[2];

      pid_t pid;

      if(pipe(fds))

      {

           printf("file:%s,line:%d",__FILE__,__LINE__);

           perror("fail pipe!");

           return ;

      }

      pid=fork();

      if(pid<0)

      {

           printf("file:%s,line:%d",__FILE__,__LINE__);

           perror("fail fork!");

           return ;

      }

      else if(pid==0)

      {

           close(fds[1]);

           dup2(fds[0],STDIN_FILENO);

           printf("\n");

           execlp("more","more","-d",NULL);

          

           close(fds[0]);

      }

      else

      {

           close(fds[0]);

          

           dup2(fds[1],STDOUT_FILENO);

           execlp("ls","ls","-b",NULL);

           close(fds[1]);

      }

}

popen 模型

FILE *popen(const char *cmd, char *type)

解析:

创建子进程,并调用exec,指向cmd命令

同时建立管道,用于父子进程标准输入输出

type取值 “ r ” :       数据由子进程流到父进程

type取值 “ w ”:       数据由父进程流到子进程

int   pclose(FILE *stream)

popen第一参数与exec的区别:

popen第一参数包括了命令的名称,参数。如:popen(”ps -ef”,”r”)作为第一参数。

exec是路径、名称、参数分开多个部分作为exec的参数传入。如exec(“ps”,”ps”,”-ef”);

例子:排序

void testPopen()

{

      int arr[]={2,4,5,77,11,22,633,21,4};

      FILE *file=popen("sort -n","w");

      if(!file)

      {

           printf("file:%s,line:%d",__FILE__,__LINE__);

           perror("fail open file!");

           return ;

      }

      int i=0;

      for(;i<sizeof(arr)/sizeof(arr[0]);++i)

      {

           fprintf(file,"%d\n",arr[i]);

      }

      pclose(file);

}

例子2:通过 popen 实现  ps -ef | grep pts

思路:

1.使用popen模型分别调用ps –ef, grep pts:

pRead = popen("ps -ef", "r")

pWrite= popen("grep pts", "w")

2.此时pRead,pWrite就是两个文件指针,进行文件读写操作。

3. 从 pRead中读取数据,写入到 pWrite中。

void testPopen2()

{

      FILE *pRead=popen("ps -ef","r");

      FILE *pWrite=popen("grep pts","w");

      if(!(pRead&&pWrite))

      {

           printf("file:%s,line:%d",__FILE__,__LINE__);

           perror("fail open file!");

           return ;

      }

      char buf[1024];

      while(fgets(buf,sizeof(buf),pRead))  

      {

           fputs(buf,pWrite);

      }

      pclose(pRead);

      pclose(pWrite);

}

猜你喜欢

转载自www.cnblogs.com/gd-luojialin/p/9216010.html