文件描述符fd, 重定向及动态库/静态库的生成与使用

文件描述符fd

我们在使用open函数以后, 正常情况下会返回一个文件描述符fd, 那么这个文件描述符是什么东西呢?
文件描述符是一个非负整数 —操作文件的句柄, 本质是一个进程打开的文件描述信息表的数组下标, 通过这个下标可以在内核中找到相应的文件描述信息, 通过这个描述信息可以实现文件操作

Linux进程默认情况下会有3个缺省打开的文件描述符, 分别是:

stdin(标准输入)0 / stdout(标准输出) 1 / stderr(标准错误) 2
文件描述符分配规则

文件描述符有个分配规则: 最小未使用, 即: 在 files_struct 数组当中, 找到当前没有被使用的最小的一个下标, 作为新的文件描述符

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

int main()
{
    int fd = open("file", O_RDONLY);

    if(fd < 0)
    {
        perror("open error");
        return -1;
    }
    printf("fd: %d\n", fd);
    close(fd);
    return 0;
}
运行结果:

在这里插入图片描述
因为文件描述符0, 1, 2分别分配给了标准输入, 标准输出和标准错误; 所以新的文件描述符从3开始

关闭0号文件描述符, 再看一下结果:

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

int main()
{
    close(0);
    int fd = open("file", O_RDONLY);

    if(fd < 0)
    {
        perror("open error");
        return -1;
    }
    printf("fd: %d\n", fd);
    close(fd);
    return 0;
}

在这里插入图片描述
这时因为0号文件描述符未使用, 有新的文件描述符就是0了

重定向

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

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

int main()
{
    close(1);
    int fd = open("file", O_WRONLY);

    if(fd < 0)
    {
        perror("open error");
        return -1;
    }
    printf("fd: %d\n", fd);
    fflush(stdout);
    close(fd);
    return 0;
}

在这里插入图片描述
执行test程序会发现终端没有任何输出, 但是file文件里写入了内容: fd: 1
因为printf打印数据到标准输出, close(1);就是把标准输出关闭了. 打开新的文件后, printf并没有把数据打印出来, 而是在刷新缓冲区以后, 将数据写入到了文件中

输出重定向: 将数据不再写入标准输出, 而是写入新的指定文件中. 实现方式就是替换这个描述符对应的文件描述信息, 实际是描述符的重定向, 改变描述符所指向的文件, 就改变了数据的流向
int dup2(int oldfd, int newfd); 描述符重定向函数
返回值: 成功时返回新的文件描述符;如果出错则返回-1
函数作用: 让newfd这个描述符也指向oldfd所指向的文件,这时候oldfd和newfd都能够操作oldfd所指向的文件

注意: 因为newfd本身有可能已经打开了文件,但是现在要让它保存oldfd指向的信息,就需要先释放掉newfd当前的信息
> 清空重定向  open(O_CREAT|O_TRUNC)
>> 追加重定向 open(O_CREAT|O_APPEND)

使用标准库IO接口时, 我们接触到文件流指针, 它与文件描述符有什么联系呢

文件描述符: 内核中文件描述信息数组的下标; pcb -> files_struct -> fd_arr[]
文件流指针: FILE结构体 —typedef struct _IO_FILE FILE —库函数IO接口的操作句柄

库函数是对函数系统调用接口的一层封装, 通过文件流指针进行最终文件操作的时候, 依然还要能够找到对应的文件描述符才可以; 文件流指针是一个结构体, 结构体中有很多成员变量, 其中有一个叫_fileno, 它就是文件描述符
向文件中写入数据, 一开始并不会直接写入文件, 而是先写入缓冲区, 刷新缓冲区的时候才会写入文件
系统调用接口是直接将数据写入文件的, 系统调用接口没有缓冲区, 但库函数存在缓冲区

动态库/静态库的生成与使用

动态库(.so): 程序在运行的时候才去链接动态库的代码, 多个程序共享使用库的代码
静态库(.a): 程序在编译链接的时候把库的代码链接到可执行文件中, 程序运行的时候将不再需要静态库

比如当前目录下有一个child.c文件

生成动态库
1.gcc -c -fPIC child.c -o child.o
2.gcc -shared child.o -o libmychild.so
fPIC:产生位置无关代码(position independent code)
shared: 表示生成共享库格式
库名规则:libxxx.so

在这里插入图片描述

使用动态库
1.拷贝.so文件到系统共享库路径下(一般是/usr/lib)
2.设置链接库的搜索路径环境变量,将当前库文件所在路径添加进去: export LD_LIBRARY_PATH = .
3.使用gcc -L选项指定链接库的搜索路径: 
  gcc main.c -o main -L./-lmychild
  -L:链接库所在的路径
  -l:链接动态库,只要库名即可

生成静态库
1.gcc -c child.c -o child.o  
2.ar -cr libmychild.a child.o

1.拷贝.a文件到系统共享库路径下(一般是/usr/lib)
2.设置链接库的搜索路径环境变量,将当前库文件所在路径添加进去: export _LIBRARY_PATH = .
3.使用gcc -L选项指定链接库的搜索路径: 
  gcc main.c -o main -L./-lmychild
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值