Linux中的重定向和管道

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Picking_up_stones/article/details/73823361

一. 重定向

重定向有输入重定向,输出重定向,追加重定向,以及错误重定向。

1.重定向命令:

输出重定向 cat file>result.txt
追加重定向 ls–l>>list.txt
错误重定向 ./myfile 2>err.txt
输入重定向 more

2.重定向在代码中的实现

  1. 实现重定向的三种方法
    (1)close … open
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
main(){
        int fd;    char buf[80];
        read(0,buf,80); write(1,buf,80);
        close(0);
        if((fd=open("/etc/passwd",O_RDONLY))!=0)      {
            perror("open"); exit(1);
        }
        read(0,buf,80); write(1,buf,80);
}

在代码中首先关闭了标准输入流,此时再打开一个文件时,采用描述符最小原则,所以此时的fd就等于0,也就是将标准输入重定向到了刚打开的文件中,此时的read就是从打开的文件中读取。

(2)open…close…dup…close
dup:复制一个文件描述符

main(){
    int fd,newfd;     char buf[80];
    read(0,buf,80); write(1,buf,80);
    fd=open("/etc/passwd",O_RDONLY);
    close(0);
    newfd=dup(fd);
    if(newfd!=0){
        perror("dup");      
        exit(1);
    }
    close(fd);
    read(0,buf,80); write(1,buf,80);
}

在代码中首先代开文件,关闭了标准输入流,然后复制文件的描述符(复制的过程相当于重新打开fd所指向的文件,因为标准输入被关闭,所以此时的新文件描述符为0),然后关闭原来的文件描述符。所以此后的读取就是从打开的文件中读取。

(3)open…dup2…close
dup2:复制一个文件描述符

main(){
    int fd,newfd;
    char buf[80];
    read(0,buf,80);    write(1,buf,80);
    fd=open("/etc/passwd",O_RDONLY);
    newfd=dup2(fd,0);
    if(newfd!=0){
    perror("dup2"); exit(1);
    }
    close(fd);
    read(0,buf,80); write(1,buf,80);
}

在代码中,首先打开文件,然后将标准输入文件描述符复制给刚才代开的文件描述符,此时标准输入被重定向到刚才打开的文件中,然后又关闭了刚才代开的文件描述符。此后的读取就是从文件中读取。

3.实现ls –l>list.txt(close then open)

#include <stdio.h> 
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
int main(void){
    int pid,fd;
    printf("This is to show how to redirect!\n");
    if((pid=fork())==-1){
        perror("fork");      
        exit(1);    
    }
    else if(pid== 0){
          close(1);              
          fd=open("list.txt",O_WRONLY|O_CREAT|O_APPEND,0644);
         if(execlp("ls","ls","-l",NULL)<0){
                perror("exec"); 
                exit(1);
          }
    }
    else if(pid!=0){
        wait(NULL); 
        system("cat list.txt");    
    }
    return 0;
}

二. 管道
管道就是特殊的文件,管道分为有名管道和匿名管道,两者的不同如下:
(1)匿名管道用pipe()创建,有名管道用mkfifo()创建;
(2)匿名管道只能实现有亲缘关系的进程之间的通信,而有名管道可以实现无亲缘关系的进程间的通信;

1.使用匿名管道实现进程间通信:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
main(){
    int pfd[2]; char buf[81];
    pid_t pid;
    if(pipe(pfd)==-1)   {
        perror("pipe"); 
        exit(1);    
    }
    printf("The pipe will read from %d, write to %d.\n", pfd[0], pfd[1]);
    pid = fork();
    if (pid == 0){
        perror("fork");
        exit(1);
    }else if (pid == 0){
        write(pfd[1],"This is write to pipe!\n",23);
    }else{
        read(pfd[0],buf,23);    
        printf("%s",buf);
        wait(NULL);
    }
    exit(0);
}

对于匿名管道来说,管道的输入和输出是固定的,0代表输入端,1代表输出端,两者不可颠倒,否则会出错。

2.使用有名管道实现进程间通信

main() {
    int pid,fd; char buf[80];
    mkfifo("fifotest",0644);  //创建有名管道,参数和open或creat函数相同
    if((pid=fork())>0)  {
        fd=open("fifotest",O_WRONLY);
        write(fd,"message to test FIFO!",22);
        close(fd);  exit(0);
    }
    else if(pid==0) {
        fd=open("fifotest",O_RDONLY);
        read(fd,buf,80);
        printf("%s\n",buf);
        close(fd);  exit(0);
    }
}

有名管道的使用方式和文件的方式是完全相同的,所以管道被叫做特殊的文件。

猜你喜欢

转载自blog.csdn.net/Picking_up_stones/article/details/73823361