当前位置: 首页 > news >正文

Linux:Bash中的文件描述符

相关阅读

Linuxicon-default.png?t=O83Ahttps://blog.csdn.net/weixin_45791458/category_12234591.html?spm=1001.2014.3001.5482


        Linux中的所有进程,都拥有自己的文件描述符(File Descriptor, FD),它是操作系统在管理进程和文件时的一种抽象概念。每个文件描述符由一个非负整数表示,用来标识进程已打开的文件、输入输出流、网络套接字等资源。一个进程可以打开的文件描述符是有上限的,可以通过ulimit命令查询,如例1所示。

# 例1
zhangchen@test:~$ ulimit -n # 查询当每个进程的文件描述符数量上限
1048576

        每个正在运行的进程,都会在虚拟文件系统的目录/proc下用一个子目录表示,目录名为进程的id号。当一个进程创建时,操作系统会为其分配一个未使用的id号并在目录/proc下创建相应的目录;当一个进程执行完毕退出时,操作系统会删除相应的目录并回收id号。

        在目录/proc/pid/fd(pid指具体的进程id号)中,可以找到名为0、1、2...的链接文件,他们指向了相应的文件描述符代表的资源,例2展示了如何查看当前Bash进程的文件描述符。

# 例2
zhangchen@test:~$ ps   # 查询Bash进程的id号PID TTY          TIME CMD
2556994 pts/3    00:00:00 bash
2557252 pts/3    00:00:00 ps
zhangchen@test:~$ ls -al /proc/2556994/fd   # 显示虚拟文件系统中bash进程的文件描述符目录
lrwx------ 1 zhangchen test 64  9月 20 13:53 0 -> /dev/pts/3
lrwx------ 1 zhangchen test 64  9月 20 13:53 1 -> /dev/pts/3
lrwx------ 1 zhangchen test 64  9月 20 13:53 2 -> /dev/pts/3
lrwx------ 1 zhangchen test 64  9月 20 13:53 255 -> /dev/pts/3

        其中文件描述符0、1、2尤为重要,它们是所有进程在创建时就默认拥有的文件描述符,分别表示标准输入(stdin)、标准输出(stdout)和标准错误输出(stderr)。从例2中可以看出它们都指向了/dev/pts/0这个伪终端设备(这是默认的行为,除非使用了重定向、管道等命令进行了重定向),这实际上指的就是当前的终端界面。

        在目录/dev下可以找到三个链接文件stdin、stdout和stderr,它们指向了当前进程的文件描述符0、1、2,如例3所示。

# 例3
zhangchen@test:~$ ls -al /dev/std* # 查询标准输入、输出、错误设备
lrwxrwxrwx 1 root root 15  7月 12 17:37 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15  7月 12 17:37 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15  7月 12 17:37 /dev/stdout -> /proc/self/fd/1

        其中/proc/self是一个链接文件,指向了当前进程的目录,也就是说如果使用ls /proc命令,则显示其指向的是进程ls的目录,如例4所示。

# 例4
zhangchen@test:~$ ls -al /proc/self  # 查询当前进程(即ls)的信息
lrwxrwxrwx 1 root root 0  7月 12 17:37 /proc/self -> 2557940 # 指向了/proc/2557940zhangchen@test:~$ ls -al /proc/self  # 查询当前进程(即ls)的信息
lrwxrwxrwx 1 root root 0  7月 12 17:37 /proc/self -> 2557972 # 指向了/proc/2557972zhangchen@test:~$ ls -al /proc/self  # 查询当前进程(即ls)的信息
lrwxrwxrwx 1 root root 0  7月 12 17:37 /proc/self -> 2557975 # 指向了/proc/2557975

        从例4中可以看出 ,连续三次使用ls命令得到的结果是不同的,这是因为每次执行ls命令都会创建一个新的进程并分配给一个未使用的id号(它们可能相等,因为执行完毕后id号会被回收,但在该例中不相等)。
        有些偏题了,我们回到文件描述符,当创建了一个新的终端并查询其文件描述符时,会发现文件描述符0、1、2指向了另一个伪终端设备/dev/pts/8,如例5所示。

# 例5
zhangchen@test:~$ ps   # 查询Bash进程的id号PID TTY          TIME CMD
2559706 pts/3    00:00:00 bash
2559728 pts/3    00:00:00 ps
zhangchen@test:~$ ls -al /proc/2559706/fd   # 显示虚拟文件系统中Bash进程的文件描述符目录
lrwx------ 1 zhangchen test 64  9月 20 13:54 0 -> /dev/pts/8
lrwx------ 1 zhangchen test 64  9月 20 13:54 1 -> /dev/pts/8
lrwx------ 1 zhangchen test 64  9月 20 13:54 2 -> /dev/pts/8
lrwx------ 1 zhangchen test 64  9月 20 13:54 255 -> /dev/pts/8

        子进程被创建时会继承父进程的文件描述符,为了验证这一点,首先介绍一个命令exec。exec命令可以用于进程替换,也可用于操作Bash进程的文件描述符,如例6所示。在此基础上如果使用sleep 100 &命令,查询其文件描述符会发现与Bash进程的相同,如例7所示。

# 例6
zhangchen@test:~$ exec 3>output.txt   # 在当前Bash进程打开一个文件描述符3,指向output.txt文件
zhangchen@test:~$ ps   # 查询Bash进程的id号PID TTY          TIME CMD
2559706 pts/3    00:00:00 bash
2559947 pts/3    00:00:00 ps
zhangchen@test:~$ ls -al /proc/2559706/fd   # 显示虚拟文件系统中Bash进程的文件描述符目录
lrwx------ 1 zhangchen test 64  9月 20 13:54 0 -> /dev/pts/8
lrwx------ 1 zhangchen test 64  9月 20 13:54 1 -> /dev/pts/8
lrwx------ 1 zhangchen test 64  9月 20 13:54 2 -> /dev/pts/8
lrwx------ 1 zhangchen test 64  9月 20 13:54 255 -> /dev/pts/8
l-wx------ 1 zhangchen test 64  9月 20 17:02 3 -> /home/zhangchen/output.txt
# 例7
zhangchen@test:~$ sleep 100 & # 一个后台执行的测试命令
[1] 2560074
zhangchen@test:~$ ls -al /proc/2560074/fd   # 显示虚拟文件系统中sleep进程的文件描述符目录
lrwx------ 1 zhangchen test 64  9月 20 17:03 0 -> /dev/pts/8
lrwx------ 1 zhangchen test 64  9月 20 17:03 1 -> /dev/pts/8
lrwx------ 1 zhangchen test 64  9月 20 17:03 2 -> /dev/pts/8
lrwx------ 1 zhangchen test 64  9月 20 17:03 255 -> /dev/pts/8
l-wx------ 1 zhangchen test 64  9月 20 17:03 3 -> /home/zhangchen/output.txt

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • C语言 | Leetcode C语言题解之题409题最长回文串
  • 深入分析几个难以理解的Comparator源码
  • 心觉:小时候常听到的这些教导,正在禁锢你的人生,该翻身了
  • 小程序开发设计-第一个小程序:注册小程序开发账号②
  • C# 比较对象新思路,利用反射技术打造更灵活的比较工具
  • 【MYSQL表的增删改查(进阶)】
  • 【JS】path的使用说明
  • 105.游戏安全项目-基址的技术原理-分析技巧
  • Unity 之 【Android Unity FBO渲染】之 [Unity 渲染 Android 端播放的视频] 的一种方法简单整理
  • Centos7更换阿里云的 YUM 镜像仓库
  • 计算机网络30——Linux-gdb调试命令makefile
  • Jenkins Docker Pipeline Clone Build Deploy mysqldump
  • 企业项目中常用的表结构设计
  • 摩托罗拉大顾问ADVISOR BP机拆解评测
  • MySQL索引测试
  • 【162天】黑马程序员27天视频学习笔记【Day02-上】
  • 4月23日世界读书日 网络营销论坛推荐《正在爆发的营销革命》
  • Android框架之Volley
  • Centos6.8 使用rpm安装mysql5.7
  • css属性的继承、初识值、计算值、当前值、应用值
  • Flex布局到底解决了什么问题
  • Java多线程(4):使用线程池执行定时任务
  • Node 版本管理
  • 关键词挖掘技术哪家强(一)基于node.js技术开发一个关键字查询工具
  • 关于for循环的简单归纳
  • 紧急通知:《观止-微软》请在经管柜购买!
  • 老板让我十分钟上手nx-admin
  • 聊聊flink的TableFactory
  • 那些被忽略的 JavaScript 数组方法细节
  • 入门级的git使用指北
  • 微信小程序开发问题汇总
  • 2017年360最后一道编程题
  • 国内唯一,阿里云入选全球区块链云服务报告,领先AWS、Google ...
  • 如何通过报表单元格右键控制报表跳转到不同链接地址 ...
  • #经典论文 异质山坡的物理模型 2 有效导水率
  • $.proxy和$.extend
  • (3)医疗图像处理:MRI磁共振成像-快速采集--(杨正汉)
  • (初研) Sentence-embedding fine-tune notebook
  • (多级缓存)缓存同步
  • (附源码)spring boot网络空间安全实验教学示范中心网站 毕业设计 111454
  • (附源码)计算机毕业设计ssm基于B_S的汽车售后服务管理系统
  • (六)Hibernate的二级缓存
  • (四)activit5.23.0修复跟踪高亮显示BUG
  • (学习日记)2024.03.12:UCOSIII第十四节:时基列表
  • (转)GCC在C语言中内嵌汇编 asm __volatile__
  • .FileZilla的使用和主动模式被动模式介绍
  • .NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划
  • .net on S60 ---- Net60 1.1发布 支持VS2008以及新的特性
  • .NET 反射的使用
  • .NET 命令行参数包含应用程序路径吗?
  • .NET 药厂业务系统 CPU爆高分析
  • .NET_WebForm_layui控件使用及与webform联合使用
  • .Net--CLS,CTS,CLI,BCL,FCL
  • .one4-V-XXXXXXXX勒索病毒数据怎么处理|数据解密恢复
  • @NestedConfigurationProperty 注解用法