I/O重定向和管道

输入输出重定向和管道是进程间的一种特殊方式。

Unix进程使用标准的文件描述符,0(stdin)、1(stdout)、2(stderr),当进程请求一个新的文件描述符的时候,系统内核将最低可用的文件描述符给它。通常情况下这三个文件描述符是打开着的。
一、I/O重定向
在Linux中,我们通过shell与系统交互,本质上就是建立进程,在进程中执行操作。 一般的输入是stdin,标准输入键盘。输出为终端界面。可以利用重定向将标准输入或输出设为传统意义文件(因为在Linux下一切皆为文件)
关于文件描述符:Unix进程使用文件描述符0、1、2作为标准输入、输出和错误的通道。其次,当进程请求一个新的文件描述符的时候,系统内核将 最低可用的文件描述符给它。
I/O重定向用到的函数有dup和dup2()
函数原型:
#include <unistd.h>
newfd = dup(oldfd);
newfd = dup2(oldfd,newfd); //一般来将先关闭掉newfd,然后复制oldfd都newfd位置
常用操作
1.close-then open
2.open-close-dup-close
example:
/*close-then-open
 *
 *
 */
#include <stdio.h>
#include <fcntl.h>

int main()
{
        int fd;
        char line[100];

        /*read and input two lines*/
        fgets(line,100,stdin); printf("%s\n",line);
        fgets(line,100,stdin); printf("%s\n",line);

        close(0);                                                /*关闭标准输入,接着创建的文件描述符自动匹配到标准输入位置上*/
        fd = open("/etc/passwd",O_RDONLY);
        if(fd == -1)
        {
                perror("open");
                exit(1);
        }
        wait(NULL);
        fgets(line,100,stdin); printf("%s\n",line);
        fgets(line,100,stdin); printf("%s\n",line);

        return 0;
}



二、管道
原型: 
#include<unistd.h>
result = pipe(int array[2]);
example:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#define BUFSIZ 10
int main()
{
        int len, i, apipe[2];
        char buf[BUFSIZ];
        char buf2[BUFSIZ];

        if(pipe(apipe) == -1){
                perror("pipe");
                exit(1);
        }

        printf("got a file descriptor %d,%d \n",apipe[0],apipe[1]);
        fgets(buf,BUFSIZ,stdin);
        len = strlen(buf);
        write(apipe[1],buf,len);

        printf("pipe exit:\n");
        read(apipe[0],buf2,len);
        printf("%s\n",buf2);
}



管道可以应用于进程中,通过子进程写,父进程读
#include<stdio.h>
#include <unistd.h>

int main()
{
    int fd;
    int pipefd[2];
    fd = fork();
    pipe(pipefd);
    if(fd  == -1)
        perror();
    else if(pid == 0)
        //write(pipe[1],buf,len); 从buf写到管道
    else
        //read(pipe[0],buf,len); 读buf到管道
    return 0;
}


三、fdopen和popen使用
fdopen使得对远端的进程的处理就像处理常规文件一样。popen函数,通过封装pipe、fork、dup、exex等系统调用使得对程序和文件的操作手法一样。

下面以一下简易计算器示例说明fdopen使用,结合了管道
#include <stdio.h>
#include <stdlib.h>
#define oops(x,m)	{perror(x);exit(m);}

void be_dc(int in[2],int out[2]);
void be_bc(int todc[],int fromdc[]);
void fatal(char*[]);

int main()
{
 <span style="white-space:pre">	</span>int pid, todc[2],fromdc[2];
 <span style="white-space:pre">	</span>if(pipe(todc) == -1 || pipe(fromdc) == -1)
 <span style="white-space:pre">		</span>oops("pipe failed",1);
 <span style="white-space:pre">	</span>if((pid = fork()) == -1)
  <span style="white-space:pre">		</span>oops("fork failed",2);
 <span style="white-space:pre">	</span>if(pid == 0)	/*child is dc*/
  <span style="white-space:pre">		</span>be_dc(todc,fromdc);
<span style="white-space:pre">	</span> else{	/*parent is ui*/
 <span style="white-space:pre">		</span> be_bc(todc,fromdc);
  <span style="white-space:pre">		</span>wait(NULL);
 <span style="white-space:pre">	</span>}
}

void be_dc(int in[2],int out[2])
/*
 *set up stdin and stdout,then execl dc
 */
{
 <span style="white-space:pre">	</span>if(dup2(in[0],0) == -1){
 <span style="white-space:pre">		</span>oops("can not dup",1);
 }
<span style="white-space:pre">	</span>close(in[0]);
 <span style="white-space:pre">	</span>close(in[1]); /*won't use*/

 <span style="white-space:pre">	</span>if (dup(out[1],1) == -1){
 <span style="white-space:pre">		</span> oops("can not dup",2);
 }
 <span style="white-space:pre">	</span>close(out[1]);
 <span style="white-space:pre">	</span>close(out[0]);/*won't use*/

 if(execlp("dc","dc","-",NULL) == -1)
  <span style="white-space:pre">	</span>oops("can not run dc\n",3);
}

void be_bc(int todc[2],int fromdc[2])
{
 <span style="white-space:pre">	</span>int num1,num2;
 <span style="white-space:pre">	</span>char operation[BUFSIZ],message[BUFSIZ],*fgets();
 <span style="white-space:pre">	</span>FILE *fpout,*fpin,*fpopen;

 <span style="white-space:pre">	</span>close(todc[0]); /*won'r read,use todc[1] to write*/
 <span style="white-space:pre">	</span>close(fromdc[1]);/*won't write,use fromdc[0] to read*/

 <span style="white-space:pre">	</span>fpout = fdopen(todc[1],"w");
 <span style="white-space:pre">	</span>fpin = fdopen(fromdc[0],"r");
<span style="white-space:pre">	</span>
 <span style="white-space:pre">	</span>if(fpout == NULL || fpin == NULL)
 <span style="white-space:pre">		</span> fatal("Error converting pipes to streams!\n");
 <span style="white-space:pre">	</span>while(printf("tiny:"),fgets(message,BUFSIZ,stdin) != NULL){
 <span style="white-space:pre">	</span> <span style="white-space:pre">	</span>if(sscanf(message,"%d %[- + * / ^] %d",&num1,operation,&num2) != 3){
 <span style="white-space:pre">			</span>  printf("sytax error!\n");
  <span style="white-space:pre">			</span> continue; 
  } 
 <span style="white-space:pre">	</span> if(fprintf(fpout,"%d\n%d\n%c\np\n",num1,num2,*operation) == EOF){
  <span style="white-space:pre">		</span> fatal("error writting!\n"); /*use p to print the result*/
  }
  <span style="white-space:pre">	</span>fflush(fpout);
  <span style="white-space:pre">	</span>if(fgets(message,BUFSIZ,fpin) == NULL)
 <span style="white-space:pre">		</span>  break;
 <span style="white-space:pre">	</span> printf("%d %s %d = %s",num1,operation,num2,message);
 }
 <span style="white-space:pre">	</span>fclose(todc[1]);
 <span style="white-space:pre">	</span>fclose(fromdc[0]);

}

void fatal(char* mess[])
{
 <span style="white-space:pre">	</span>fprintf(stderr,"Error:%s\n",mess);
 <span style="white-space:pre">	</span>exit(1);
}


popen使用
FILE* fp;
fp = popen("ls","r");
fgets(buf,len,fp);
pclose(fp);
示例:
#include <stdio.h>
#include <stdlib.h>

int main()
{
 <span style="white-space:pre">	</span>FILE* fp;
<span style="white-space:pre">	</span>char buf[100];
<span style="white-space:pre">	</span>int i = 0;

 <span style="white-space:pre">	</span>fp = popen("who | sort","r");
 <span style="white-space:pre">	</span>while(fgets(buf,100,fp) != NULL){
  <span style="white-space:pre">	</span><span style="white-space:pre">	</span>printf(" %3d %s\n",i++,buf);
 <span style="white-space:pre">	</span>}
 <span style="white-space:pre">	</span>fclose(fp);
 <span style="white-space:pre">	</span>return 0;
}




猜你喜欢

转载自blog.csdn.net/xingzhibo/article/details/43227881
今日推荐