Linux -文件描述符

1.文件描述符

通过对open函数的学习,我们知道了文件描述符就是一个小整数

1.1 0 & 1 & 2

Linux进程默认情况下会有3个缺省打开的文件描述符,分别是标准输入0, 标准输出1, 标准错误2。
0,1,2对应的物理设备一般是:键盘,显示器,显示器。
所以输入输出还可以采用如下方式:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main()
{
 char buf[1024];
 ssize_t s = read(0, buf, sizeof(buf));
 if(s > 0){
 buf[s] = 0;
 write(1, buf, strlen(buf));
 write(2, buf, strlen(buf));
 }
 return 0;
}

在这里插入图片描述
运行后显示要求输入值:
在这里插入图片描述
标准输入流读取后,在标准输出流和标准错误流中输出,也就是从键盘读取后输出到屏幕上。

在这里插入图片描述
而现在知道,文件描述符就是从0开始的小整数。当我们打开文件时,操作系统在内存中要创建相应的数据结构来描述目标文件。于是就有了file结构体。表示一个已经打开的文件对象。而进程执行open系统调用,所以必须让进程和文件关联起来。每个进程都有一个指针*files, 指向一张表files_struct,该表最重要的部分就是包涵一个指针数组,每个元素都是一个指向打开文件的指针!所以,本质上,文件描述符就是该数组的下标。所以,只要拿着文件描述符,就可以找到对应的文件

1.2文件描述符分配规则

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
 int fd = open("myfile", O_RDONLY);
 if(fd < 0){
 perror("open");
 return 1;
 }
 printf("fd: %d\n", fd);
 close(fd);
 return 0;
}

在这里插入图片描述
发现fd等于3

关闭0或者2,在看:

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
 close(0);
 //close(2);
 int fd = open("myfile", O_RDONLY);
 if(fd < 0){
 perror("open");
 return 1;
 }
 printf("fd: %d\n", fd);
 close(fd);
 return 0;
}

在这里插入图片描述
发现是结果是: fd: 0 可见,文件描述符的分配规则:files_struct数组当中,找到当前没有被使用的最小的一个下标,作为新的文件描述符。

2.重定向

如果关闭文件描述符1呢?

#include<unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
int main()
{
 close(1);
 int fd = open("myfile", O_WRONLY|O_CREAT, 00644);
 if(fd < 0){
 perror("open");
 return 1;
 }
 printf("fd: %d\n", fd);
 fflush(stdout);
 
 close(fd);
 exit(0);
}

在这里插入图片描述
在这里插入图片描述
此时,我们发现,本来应该输出到显示器上的内容,输出到了文件 myfile 当中,其中,fd=1。这种现象叫做输出重定向。常见的重定向有:>, >>, <

在这里插入图片描述
重定向的本质就是改变这些文件描述符所指向的位置,使其指向用户指定的文件或其他资源。

3.dup2系统调用

3.1 dup2函数基本信息

dup2是Unix/Linux系统中一个重要的系统调用函数,用于复制文件描述符,并将其重定向到指定的新文件描述符上

函数原型:

int dup2(int oldfd, int newfd);

参数:
oldfd:待复制的文件描述符。
newfd:指定的新文件描述符。

返回值:成功时返回newfd,出错时返回-1。

man dup查看详细信息
在这里插入图片描述

3.2工作原理

检查oldfd和newfd是否相等:如果两者相等,则不进行任何操作,直接返回newfd。
检查newfd的合法性:如果newfd已经打开,则先关闭它。
复制oldfd的文件表项到newfd:使得newfd和oldfd指向同一个文件表项,共享相同的文件偏移量和文件状态标志。
返回newfd:此时,newfd和oldfd都指向同一个文件,但可以通过不同的文件描述符进行操作。

3.3常见用途

重定向标准输入、输出和错误输出:通过dup2函数,可以将文件描述符与标准输入(stdin,文件描述符0)、标准输出(stdout,文件描述符1)和错误输出(stderr,文件描述符2)进行关联,实现输入输出的重定向。例如,将标准输出重定向到文件中,以便将程序的输出结果保存到文件中。
管道通信:在进程间通信中,管道是一种常用的通信方式。通过dup2函数,可以将管道的读端或写端复制到标准输入或标准输出,从而实现进程间的数据传输和信息交换。
文件描述符的复制:有时候需要复制一个文件描述符,以便在不同的上下文中使用。通过dup2函数,可以创建一个新的文件描述符,并复制旧的文件描述符的状态,使得两者指向同一个文件表项。这样做的好处是在不改变原来文件描述符设置的情况下,可以在新的文件描述符上进行操作。

3.4示例

使用dup2函数将标准输出重定向到文件:

#include <unistd.h>  
#include <stdio.h>  
#include <fcntl.h>  
  
int main() {  
    int fd = open("output.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);  
    if (fd == -1) {  
        perror("open");  
        return -1;  
    }  
  
    // 将标准输出重定向到文件  
    if (dup2(fd, STDOUT_FILENO) == -1) {  
        perror("dup2");  
        close(fd);  
        return -1;  
    }  
  
    // 此时,标准输出已经重定向到文件,接下来的printf将输出到文件  
    printf("Hello, World!\n");  
  
    // 关闭原始的文件描述符(可选,因为进程结束时会自动关闭)  
    close(fd);  
  
    return 0;  
}

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

gsfl

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

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

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

打赏作者

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

抵扣说明:

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

余额充值