[Linux]重定向

一、struct file内核对象

struct file是在内核中创建,专门用来管理被打开文件的结构体。struct file中包含了打开文件的所有属性,文件的操作方法集以及文件缓冲区(无论读写,我们都需要先将数据加载到文件缓冲区中。等等。

我们在应用层进行数据的读写,本质是将内核缓冲区中的数据,进行来回拷贝。

二、文件描述符fd分配规则

1、进程默认打开0、1、2

我们可以直接使用0,1,2进行数据访问。

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>


int main()
{
  char buf[1024];
  ssize_t s = read(0, buf, 1024);
  if(s > 0)
  {
    buf[s-1] = 0;//这样我们最后输入的那个回车(换行)就不会被打印

    write(1,buf,strlen(buf));
   // printf("%s\n",buf);
  }



  return 0;
}

运行程序后,程序等待我们输入:

 

随意输入字符:

 

按下回车:

 

程序执行完毕。

 2、寻找最小&&未被使用的数据的位置,分配给指定的打开文件

验证:

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>


int main()
{
  close(0);

  int fd = open("test.txt",O_WRONLY | O_CREAT | O_TRUNC, 0666);
  printf("fd:%d\n",fd);
  close(fd);

  return 0;
}

此时我们打开的这个test.txt文件,其fd就成了0:

  

三、重定向

1、输出重定向:

那么,如果我们close(1)呢?

(1)close(1)

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>


int main()
{
  close(1);
  int fd = open("log.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);
  if(fd < 0)
  {
    perror("open");
    return 1;
  }

  printf("fd:%d\n",fd);

  close(fd);

  return 0;
}

可以看到,屏幕未输出任何东西,log.txt文件中也没有内容:

(2)fflush(stdout)

当我们刷新fflush(stdout)时:

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>


int main()
{
  close(1);
  int fd = open("log.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);
  if(fd < 0)
  {
    perror("open");
    return 1;
  }

  printf("fd:%d\n",fd);
  printf("stdout->%d\n",stdout->_fileno);
  fflush(stdout);
  close(fd);

  return 0;
}

运行程序:

我们将其称为:输出重定向。 

(3)总结:

上层并不知道我们将1号文件描述符的指向改变了,printf()打印的本质是向1号文件描述符里面打印,具体1号文件描述符指向的是显示器,就向显示器打印,指向的是文件,就向文件里打印。所以这里,printf()就向log.txt里面打印了。

重定向的 本质就是修改 文件描述符表 特定数组下标 里面的内容。

2、输入重定向:

我们首先向log.txt文件中写入数据:

 我们首先close(0),然后再打开log.txt,这样log.txt的文件描述符fd就是0。

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>


int main()
{
  close(0);

  char buf[1024];
  int fd = open("log.txt",O_RDONLY);
  if(fd < 0)
  {
    perror("open");
    return 1;
  }

  fread(buf,1,sizeof buf,stdin);
  buf[strlen(buf)-1] = 0;//将"\n"符号改为0
  printf("%s\n",buf);

  return 0;
}

 运行程序,我们可以看到,log.txt文件中的内容被打印出来了:

3、原理:

上层的fd不变,底层fd指向的内容在改变。 

4、使用

 我们这里使用dup2:

将oldfd的数组内容拷贝到newfd的数组内容中。

需要注意的是,这样就会导致有多个fd指向一个打开的文件,为了避免一个fd把文件关闭的时候,影响到其余的fd,在struct file中,存在一个f_count用来计数,有几个指针指向该文件,f_count就为几。

我们首先查看log.txt中的内容:

 

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>


int main()
{
  int fd = open("log.txt",O_APPEND | O_WRONLY);
  if(fd < 0)
  {
    perror("open");
    return 1;
  }

  dup2(fd,1);
  printf("haha\n");
  fprintf(stdout,"yeye\n");

  close(fd);
  
  return 0;
}

然后执行程序:

可以看出文件内新增了内容。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杯酒问苍天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值