>  기사  >  운영 및 유지보수  >  lsof로 시작하여 Linux 가상 파일 시스템에 대한 심층적인 이해를 얻으세요.

lsof로 시작하여 Linux 가상 파일 시스템에 대한 심층적인 이해를 얻으세요.

Linux中文社区
Linux中文社区앞으로
2023-08-04 16:15:491526검색

Background

가끔 디스크 공간이 꽉 차는 경우가 있는데, 디스크의 구체적인 파일 점유를 확인해 보면 여전히 디스크에 여유 공간이 많이 남아 있는 것을 발견할 수 있습니다.
1. <code style="margin-right: 0.15em;margin-left: 0.15em;padding-right: 0.3em;padding-left: 0.3em;font-size: 0.85em;font-family: Consolas, Inconsolata, Courier, monospace;white-space: pre-wrap;border-width: 1px;border-style: solid;border-color: rgb(234, 234, 234);background-color: rgb(248, 248, 248);border-radius: 3px;display: inline;"><span style="font-size: 15px;">df</span>df 명령을 사용하여 디스크 사용량을 확인했는데 디스크가 꽉 찼음을 확인했습니다.

-bash-4.2$ df -ThFilesystem     Type      Size  Used Avail Use% Mounted on/dev/vda1      ext4       30G    30G 0         100% /devtmpfs       devtmpfs  489M     0  489M   0% /devtmpfs          tmpfs     497M     0  497M   0% /dev/shmtmpfs          tmpfs     497M   50M  447M  11% /runtmpfs          tmpfs     497M     0  497M   0% /sys/fs/cgroup

2. du 명령을 실행하여 각 디렉토리의 디스크 사용량을 확인하고, 각 디렉토리의 파일 크기를 합산하여 디스크가 비어 있고, 공간이 10G 이상임을 확인합니다. 설명할 수 없을 정도로 누락되었습니다.


-bash-4.2$ du -h --max-depth=1 /home16M    /home/logs11G    /home/serverdog11G    /home

🎜
3.为何会出现这样的情况呢?
因为虽然文件已被删除,但是一些进程仍然打开这些文件,因此其占用的磁盘空间并没有被释放。执行<span style="font-size: 15px;">lsof</span> 命令显示打开已删除的文件。将有问题的进程重启(或,清空),磁盘空间就会得到释放。
-bash-4.2# lsof | grep deletemysqld     2470         mysql    4u      REG              253,1           0     523577 /var/tmp/ibfTeQFn (deleted)mysqld     2470         mysql    5u      REG              253,1           0     523579 /var/tmp/ibaHcIdW (deleted)mysqld     2470         mysql    6u      REG              253,1           0     523581 /var/tmp/ibLjiALu (deleted)mysqld     2470         mysql    7u      REG              253,1           0     523585 /var/tmp/ibCFnzTB (deleted)mysqld     2470         mysql   11u      REG              253,1           0     523587 /var/tmp/ibCjuqva (deleted)

那么,Linux 的文件系统,到底为什么这么设计呢?要了解这些,就要先弄清楚并不容易,下面将从一些基本概念入手,一步步将这些梳理清楚:
  • 什么是虚拟文件系统(VFS:virtual filesystem)?

  • 什么是通用文件模型?

    • 超级块对象(superblock object)

    • 索引节点对象(inode object)

    • 文件对象(file object)

    • 目录项对象(dentry object)

    • 文件的概念

  • 文件的表达

    • 内存表达

    • 磁盘表达

  • 目录树的构建

    • 소프트 링크와 하드 링크

  • 파일 및 디스크 관리

    • 색인 상태

  • 파일 및 프로세스 관리

    • 작업:

      열기 및 삭제

가상 파일 시스템

다음 그림은 Linux 운영 체제에서 파일 관리를 담당하는 기본 구성 요소를 보여줍니다. 위쪽이 사용자 모드, 아래쪽이 커널 모드입니다. 애플리케이션은 표준 라이브러리 libc를 사용하여 파일에 액세스하고 라이브러리는 커널 모드로 들어가기 위해 요청을 시스템 호출에 매핑합니다.

lsof로 시작하여 Linux 가상 파일 시스템에 대한 심층적인 이해를 얻으세요.

모든 파일 관련 작업의 진입점은 특정 파일 시스템(예: Ext3, ReiserFS 및 NFS)이 아닌 가상 파일 시스템(VFS)입니다. VFS는 시스템 라이브러리와 특정 파일 시스템 간의 인터페이스를 제공합니다. 따라서 VFS는 추상화 계층의 역할을 할 뿐만 아니라 실제로 다양한 구현에 의해 사용 및 확장될 수 있는 파일 시스템의 기본 구현을 제공합니다. 따라서 파일 시스템의 작동 방식을 이해하려면 먼저 VFS를 이해해야 합니다.

공통 파일 모델

VFS의 주요 아이디어는 공통 파일 모델을 도입하는 것입니다. 일반적인 파일 모델은 다음과 같은 객체 유형으로 구성됩니다.

슈퍼블록 객체

메모리: 파일 시스템이 설치될 때 생성되며, 파일 시스템에 대한 관련 정보를 저장합니다.
디스크: 슈퍼블록에 저장된 정보에 해당합니다. disk 파일 시스템 제어 블록(filesystem control block)

Inode 객체(inode 객체)

Memory : 접근 시 생성, 특정 파일에 대한 일반 정보를 저장(inode 结构)
Disk : 디스크의 저장소에 해당 파일 제어
각 inode 객체에는 파일 시스템의 파일을 고유하게 식별하는 inode 번호가 있습니다

파일 객체(file object)

Memory: 파일이 열릴 때 생성되며, 열린 파일과 프로세스 간의 상호 작용에 대한 정보를 저장합니다(파일 구조) <code style="margin-right: 0.15em;margin-left: 0.15em;padding-right: 0.3em;padding-left: 0.3em;font-size: 0.85em;font-family: Consolas, Inconsolata, Courier, monospace;white-space: pre-wrap;border-width: 1px;border-style: solid;border-color: rgb(234, 234, 234);background-color: rgb(248, 248, 248);border-radius: 3px;display: inline;">file 结构
打开文件信息,仅当进程访问文件期间存在于内核内存中。

目录项对象(dentry object)

内存:目录项一旦被读入内存,VFS就会将其转换成dentry 结构열린 파일 정보는 프로세스가 파일에 접근하는 동안에만 커널 메모리에 존재합니다.

Dentry 객체

Memory: 디렉토리 항목이 메모리로 읽혀지면 VFS는 이를 덴트리 구조 디렉토리 항목 개체 디스크: 특정 파일 시스템은 특정 방식으로 디스크에 저장됩니다.

디렉토리 항목(예: 파일 이름)과 해당 파일 사이의 링크에 대한 정보를 저장합니다. 🎜🎜🎜🎜 디렉토리 트리 🎜🎜🎜🎜 요약하자면, Linux의 루트 파일 시스템은 (시스템의 루트 파일 시스템)은 커널이 마운트를 시작하는 첫 번째 파일 시스템입니다. 커널 코드 이미지 파일은 루트 파일 시스템에 저장되며 시스템 부팅 프로그램은 루트 파일 시스템이 마운트된 후 실행하기 위해 일부 기본 초기화 스크립트와 서비스를 메모리에 로드합니다(파일 시스템과 커널은 두 부분으로 완전히 독립적입니다). ). 이후 다른 파일 시스템은 스크립트나 명령을 통해 파일 시스템이 설치된 디렉토리에 하위 파일 시스템으로 설치되어 결국 전체 디렉토리 트리를 형성합니다. 🎜🎜
start_kernel   vfs_caches_init     mnt_init       init_rootfs     // 注册rootfs文件系统      init_mount_tree // 挂载rootfs文件系统   …   rest_init   kernel_thread(kernel_init, NULL, CLONE_FS);

就单个文件系统而言,在文件系统安装时,创建超级块对象;沿树查找文件时,总是首先从初识目录的中查找匹配的目录项,以便获取相应的索引节点,然后读取索引节点的目录文件,转化为dentry对象,再检查匹配的目录项,反复执行以上过程,直至找到对应的文件的索引节点,并创建索引节点对象。

软链接 vs 硬链接

软链接是一个普通的文件,其中存放的是另外一个文件的路径名。硬链接则指向同一个索引节点,硬链接数记录在索引节点对象的 i_nlink 字段。当<span style="font-size: 15px;color: rgb(68, 68, 68);">i_nlink</span>字段为零时,说明没有硬链接指向该文件。

文件 & 进程管理

下图是一个简单示例,说明进程是怎样与文件进行交互。三个不同进程打开同一个文件,每个进程都有自己的文件对象,其中两个进程使用同一个硬链接(每个硬链接对应一个目录对象),两个目录项对象都指向同一个 索引节点对象。

lsof로 시작하여 Linux 가상 파일 시스템에 대한 심층적인 이해를 얻으세요.

索引节点的数据又由两部分组成:内存数据和磁盘数据。Linux 使用 Write back 作为索引节点的数据一致性策略。对于索引节点的数据,当文件被打开时,才会加载索引节点到内存;当不再被进程使用,则从内存踢出;如果中间有更新,则需要把数据写回磁盘。
*  "in_use" - valid inode, i_count > 0, i_nlink > 0*  "dirty"  - as "in_use" but also dirty*  "unused" - valid inode, i_count = 0

인덱스 노드가 아직 사용 중인지 여부는 <code style="margin-right: 0.15em;margin-left: 0.15em;padding-right: 0.3em;padding-left: 0.3em;font-size: 0.85em;font-family: Consolas, Inconsolata, Courier, monospace;white-space: pre-wrap;border-width: 1px;border-style: solid;border-color: rgb(234, 234, 234);background-color: rgb(248, 248, 248);border-radius: 3px;display: inline;"><span style="font-size: 15px;">open()</span> 和 <span style="font-size: 15px;">close()</span> 操作建立和销毁文件对象,文件对象通过索引节点提供的 <span style="font-size: 15px;">iget</span> 和 <span style="font-size: 15px;">iput</span>  更新索引节点的i_count字段,以完成使用计数。open 操作使得 i_count 加一, close 操作使得 i_count 减一。在 close 操作时判断索引节点是否释放,如果 i_count = 0,则意味着不再有进程引用,将会从内存释放。

文件 & 磁盘管理

文件与磁盘管理联系最紧密的操作,莫过于<span style="font-size: 15px;">touch</span><span style="font-size: 15px;">rm</span>open()

🎜close( )🎜 🎜 작업은 파일 개체를 생성하고 삭제합니다. 파일 개체는 인덱스 노드 🎜🎜iget🎜🎜 및 🎜 🎜iput🎜🎜 인덱스 노드의 i_count 필드를 업데이트하여 사용 횟수를 완료합니다. open 연산은 i_count를 1만큼 증가시키고, close 연산은 i_count를 1만큼 감소시킵니다. 닫기 작업 중에 인덱스 노드가 해제되는지 확인합니다. i_count = 0이면 더 이상 프로세스 참조가 없으며 메모리에서 해제된다는 의미입니다. 🎜🎜

파일 및 디스크 관리🎜

🎜파일 디스크 관리와 가장 밀접하게 관련된 작업은 🎜🎜touch🎜🎜 및 🎜🎜rm🎜🎜 작업, 특히 후자가 가장 중요합니다. strace(또는 dtruss)를 사용하여 rm🎜🎜의 실제 시스템 호출을 확인하세요.

# dtruss rm tmp...geteuid(0x0, 0x0, 0x0)         = 0 0ioctl(0x0, 0x4004667A, 0x7FFEE06F09C4)         = 0 0lstat64("tmp\0", 0x7FFEE06F0968, 0x0)         = 0 0access("tmp\0", 0x2, 0x0)         = 0 0unlink("tmp\0", 0x0, 0x0)         = 0 0

可以发现 rm 实际是通过 unlink 完成的。unlink代表删除目录项,以及减少其索引节点的计数。由通用文件模型可知,父目录本身同样是一个文件,也就意味着目录项是其文件数据的一部分。删除目录项等价于从父目录的文件中删除数据,也就意味着首先要打开父目录的文件。那么,删除操作即可理解为:

  1. 删除命令(一个进程)使用 open 操作获得父目录文件对象

  2. 通过 <span style="font-size: 15px;color: rgb(68, 68, 68);">iget</span> 增加 目录文件的索引节点对象计数

  3. 读取目录文件数据

  • 将目录文件数据转化为目录项对象

  • 由于目录项包含文件的索引节点,类似的,需要通过 iget 增加文件的索引节点对象计数

  • 删除目录的目录项

  • 减少文件索引节点对象的硬链接计数i_nlink

  • 通过 <span style="font-size: 15px;color: rgb(68, 68, 68);">iput</span> 结束对文件索引节点对象的操作,使用计数 i_count 减一

    • 判断i_count是否为零,如果为零,则释放内存

    • 然后,判断i_nlink是否为零,如果为零,则释放磁盘空间

  • 通过 iput 结束对目录索引节点对象的操作。

  • 요약

    발생한 문제를 되돌아보면 실제로 두 가지 관점에서 이해할 수 있습니다.

    인덱스 및 데이터

    파일 시스템 및 파일, 디스크 관리 및 파일, 프로세스 관리 및 파일 핵심은 파일의 데이터가 아니라 파일의 인덱스입니다. 데이터와 인덱스를 분리하는 것은 파일 시스템을 이해하는 데 중요합니다.


    lsof로 시작하여 Linux 가상 파일 시스템에 대한 심층적인 이해를 얻으세요.

    캐싱 전략

    운영 체제는 Write back 전략을 사용하므로 메모리가 먼저 해제되어야만 디스크가 해제될 수 있다는 의미입니다.

    왜 lsof인가?

    디렉토리는 더 이상 파일에 대해 인덱싱되지 않지만 파일을 열 때 파일은 여전히 ​​인덱싱되어 있으므로 디스크 공간을 즉시 해제할 수 없기 때문에 위 모델에서 명확하게 이해할 수 있습니다. .
    lsof가 삭제된 파일과 출시되지 않은 파일을 찾을 수 있는 이유는 무엇입니까?
    lsof, 이름에서 알 수 있듯이: list open files, 이 명령의 원리는 열려 있는 파일 목록을 찾는 것이므로 삭제되었지만 해제되지 않은 파일을 찾을 수 있습니다.

위 내용은 lsof로 시작하여 Linux 가상 파일 시스템에 대한 심층적인 이해를 얻으세요.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 Linux中文社区에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제