• Linux之从进程角度来理解文件描述符


    文件描述符是一个非负整数,而内核需要通过这个文件描述符才可以访问文件。当我们在系统中打开已有的文件或新建文件时,内核每次都会给特定的进程返回一个文件描述符,当进程需要对文件进行读或写操作时,都要依赖这个文件描述符进行。
    在Linux或类UNIX系统中内核默认会为每个进程创建三个标准的文件描述符,分别是0(标准输入)、1(标准输出)和2(标准错误)。

    通过查看/proc/PID号/fd/目录下的文件,就可以查看每个进程拥有的所有文件描述符。

    mango@mango-ubuntu:~/Documents/filedesc$ sudo ls -l /proc/$$/fd
    total 0
    lrwx------ 1 mango mango 64  524 11:08 0 -> /dev/pts/1
    lrwx------ 1 mango mango 64  524 11:08 1 -> /dev/pts/1
    lrwx------ 1 mango mango 64  524 11:08 2 -> /dev/pts/1
    lrwx------ 1 mango mango 64  524 11:08 255 -> /dev/pts/1
    
    

    当打开文件时系统内核就会为特定的进程自动创建对应的文件描述符。
    首先在一个Terminal中使用vi打开temp文件;

    mango@mango-ubuntu:~/Documents/filedesc$ vi temp
    
    

    新打开一个Terminal并查看此进程的fd信息;

    mango@mango-ubuntu:~/Documents/filedesc$ sudo ps -a   | grep vi
       8888 pts/1    00:00:00 vi
    mango@mango-ubuntu:~/Documents/filedesc$ sudo ls -l /proc/8888/fd
    total 0
    lrwx------ 1 mango mango 64  524 11:22 0 -> /dev/pts/1
    lrwx------ 1 mango mango 64  524 11:22 1 -> /dev/pts/1
    lrwx------ 1 mango mango 64  524 11:22 2 -> /dev/pts/1
    lrwx------ 1 mango mango 64  524 11:22 3 -> /home/mango/Documents/filedesc/.temp.swp
    
    

    我们也可以手动定义文件描述符,并通过文件描述符操作文件;

    创建文件描述符

    exec文件描述符 <> 文件名
    

    引用文件描述符

    &文件描述符
    

    关闭文件描述符

    exec文件描述符<&-
    exec文件描述符>&-
    

    我们touch一个文件,并将其文件描述符设置为10,并通过这个文件描述符来操作文件;

    mango@mango-ubuntu:~/Documents/filedesc$ touch testfile11
    mango@mango-ubuntu:~/Documents/filedesc$ sudo ls -l /proc/$$/fd
    total 0
    lrwx------ 1 mango mango 64  524 11:39 0 -> /dev/pts/2
    lrwx------ 1 mango mango 64  524 11:39 1 -> /dev/pts/2
    lrwx------ 1 mango mango 64  524 11:39 2 -> /dev/pts/2
    lrwx------ 1 mango mango 64  524 11:39 255 -> /dev/pts/2
    mango@mango-ubuntu:~/Documents/filedesc$ exec 10>testfile11
    mango@mango-ubuntu:~/Documents/filedesc$ echo hello >&10
    mango@mango-ubuntu:~/Documents/filedesc$ echo "world">&10
    mango@mango-ubuntu:~/Documents/filedesc$ cat testfile11
    hello
    world
    mango@mango-ubuntu:~/Documents/filedesc$ exec 10<&-
    mango@mango-ubuntu:~/Documents/filedesc$ echo "closed">&10
    bash: 10: Bad file descriptor
    
    

    如果我们设置文件描述符只允许读,那么我们写文件的时候就会报错;

    mango@mango-ubuntu:~/Documents/filedesc$ exec 11@mango-ubuntu:~/Documents/filedesc$ cat <&11
    hello
    world
    mango@mango-ubuntu:~/Documents/filedesc$ cat <&11
    mango@mango-ubuntu:~/Documents/filedesc$ exec 11@mango-ubuntu:~/Documents/filedesc$ echo "world">&11
    bash: echo: write error: Bad file descriptor
    mango@mango-ubuntu:~/Documents/filedesc$ ls -l /proc/$$/fd
    total 0
    lrwx------ 1 mango mango 64  524 11:39 0 -> /dev/pts/2
    lrwx------ 1 mango mango 64  524 11:39 1 -> /dev/pts/2
    lr-x------ 1 mango mango 64  524 11:52 11 -> /home/mango/Documents/filedesc/testfile11
    lrwx------ 1 mango mango 64  524 11:39 2 -> /dev/pts/2
    lrwx------ 1 mango mango 64  524 11:39 255 -> /dev/pts/2
    mango@mango-ubuntu:~/Documents/filedesc$ exec 11<&-
    mango@mango-ubuntu:~/Documents/filedesc$ ls -l /proc/$$/fd
    total 0
    lrwx------ 1 mango mango 64  524 11:39 0 -> /dev/pts/2
    lrwx------ 1 mango mango 64  524 11:39 1 -> /dev/pts/2
    lrwx------ 1 mango mango 64  524 11:39 2 -> /dev/pts/2
    lrwx------ 1 mango mango 64  524 11:39 255 -> /dev/pts/2
    
    

    我们也可以创建一个同时可读可写的文件描述符;

    mango@mango-ubuntu:~/Documents/filedesc$ exec 11<>testfile11
    mango@mango-ubuntu:~/Documents/filedesc$ cat <&11
    hello
    world
    mango@mango-ubuntu:~/Documents/filedesc$ echo "read write" >&11
    mango@mango-ubuntu:~/Documents/filedesc$ cat <&11
    mango@mango-ubuntu:~/Documents/filedesc$ exec 11<>testfile11
    mango@mango-ubuntu:~/Documents/filedesc$ cat <&11
    hello
    world
    read write
    mango@mango-ubuntu:~/Documents/filedesc$ exec 11<&-
    mango@mango-ubuntu:~/Documents/filedesc$ cat <&11
    bash: 11: Bad file descriptor
    
  • 相关阅读:
    《Video MAE》何恺明团队提出视频版本的MAE,进行高效视频预训练!Mask Ratio高达90%时效果很好!...
    mysql聚簇索引和主键索引的区别
    全量知识系统 详细程序设计 之“编程理念”(Q&A SmartChat)
    RabbitMQ消息队列的工作模式
    AI只需26秒,就可以设计一款会走路的机器人
    强化学习问题(四)--- NameError: name ‘glPushMatrix‘ is not defined
    手把手教你写一个JSON在线解析的前端网站1
    .net餐厅管理系统数据层OperServer服务类
    TCP 协议的相关(部分)特性
    boost之内存管理
  • 原文地址:https://www.cnblogs.com/wufengtinghai/p/17437733.html