ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

深入理解Linux内核--文件描述符,文件对象,索引节点,虚拟文件系统,性能优化

深入理解Linux内核--文件描述符,文件对象,索引节点,虚拟文件系统,性能优化 1.核心数据结构关系用户空间 内核空间 │ │ ▼ ▼ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ fd │───▶│ file │──▶│ inode │──▶│ sb │ │(int)│ │(struct)│ │(struct)│ │(struct)│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │ │ │ │ f_op i_op s_op │(file_ops)(inode_ops)(super_ops)│ │ │ │ ▼ ▼ ▼ ▼ 进程FD表 VFS层 具体文件系统 块设备层2.各核心概念详解2.1.文件描述符File Descriptor本质进程级整数索引指向内核的 struct file进程 task_struct └── files_struct └── fd_array[NR_OPEN_DEFAULT]// 默认 64 项├── fd[0]→structfile*// stdin├── fd[1]→structfile*// stdout├── fd[2]→structfile*// stderr└── fd[3]→structfile*// 打开的文件关键特性进程私有每个进程独立维护 fd 表继承性fork() 时复制exec() 时保留除非 O_CLOEXEC最小分配总是返回最小可用整数2.2.文件对象struct file本质打开文件的动态视图代表一次打开操作structfile{structpathf_path;// 文件路径 (dentry vfsmount)structinode*f_inode;// 指向 inodeconststructfile_operations*f_op;// 操作方法集loff_tf_pos;// 当前读写位置fmode_tf_mode;// 打开模式 (O_RDONLY, O_RDWR...)structfown_structf_owner;// 用于信号驱动 I/Ounsignedintf_flags;// 打开标志 (O_NONBLOCK, O_SYNC...)structlist_headf_ep_links;// epoll 关联structaddress_space*f_mapping;// 页缓存映射// ...};重要区分概念生命周期数量关系struct file打开到关闭N 个进程可共享同一 filedup/forkstruct inode文件存在期间1 个 inode 可被多个 file 引用2.3.索引节点struct inode本质文件的静态元数据唯一标识一个文件structinode{umode_ti_mode;// 文件类型 权限uid_ti_uid;// 属主gid_ti_gid;// 属组loff_ti_size;// 文件大小structtimespec64i_atime;// 访问时间structtimespec64i_mtime;// 修改时间structtimespec64i_ctime;// 变更时间structsuper_block*i_sb;// 所属超级块conststructinode_operations*i_op;// inode 操作structaddress_space*i_mapping;// 页缓存地址空间// 文件系统私有数据union{structext4_inode_infoext4_i;structxfs_inodexfs_i;// ...};};关键机制inode cache内核缓存最近使用的 inode避免重复读取磁盘引用计数i_count内存引用和 i_nlink硬链接数i_hash全局哈希表加速查找3.虚拟文件系统VFS本质抽象层统一所有文件系统的接口┌─────────────────────────────────────┐ │ 系统调用层 │ │(open/read/write/close/mmap...)│ └─────────────┬───────────────────────┘ ▼ ┌─────────────────────────────────────┐ │ VFS 层 │ │ ┌─────────┐ ┌─────────┐ ┌──────┐ │ │ │ file ops│ │inode ops│ │sb ops│ │ │ │generic_ │ │generic_ │ │ │ │ │ │read()│ │create()│ │ │ │ │ └─────────┘ └─────────┘ └──────┘ │ └─────────────┬───────────────────────┘ ▼ ┌─────────────────────────────────────┐ │ 具体文件系统层 │ │ ext4 │ xfs │ btrfs │ nfs │ fuse │ └─────────────┬───────────────────────┘ ▼ ┌─────────────────────────────────────┐ │ 块设备/网络层 │ │ ┌─────┐ ┌─────┐ ┌─────┐ │ │ │SCSI │ │NVMe │ │NFS │ │ │ └─────┘ └─────┘ └─────┘ │ └─────────────────────────────────────┘VFS 核心对象对象作用关键操作super_block文件系统实例s_op: mount/umount/statfsinode文件元数据i_op: create/link/unlinkdentry目录项缓存d_op: d_hash/d_comparefile打开文件f_op: read/write/mmap/polladdress_space页缓存管理a_ops: readpage/writepage4.性能优化4.1.页缓存Page Cache优化// 核心结构structaddress_space{structinode*host;// 所属 inodestructradix_tree_rootpage_tree;// 页缓存 radix 树spinlock_ttree_lock;conststructaddress_space_operations*a_ops;// readpage/writepage/write_begin/write_end};优化手段技术原理适用场景预读Readahead顺序读取时提前加载后续页大文件顺序读延迟写Writeback脏页不立即刷盘批量回写写密集型mmap MAP_POPULATE预建立页表映射启动时加载posix_fadvise提示访问模式数据库、日志# 查看页缓存命中率 cat/proc/vmstat|grep-Epgpgin|pgpgout|pswpin|pswpout# 调整脏页回写阈值 sysctl vm.dirty_ratio40# 脏页占总内存比例 sysctl vm.dirty_expire_centisecs3000# 脏页过期时4.2.目录项缓存Dentry Cache / DCACHE作用缓存路径解析结果避免重复遍历目录# 查看 dentry cache 状态 cat/proc/slabinfo|grep dentry # 手动清理谨慎使用 echo2/proc/sys/vm/drop_caches # 清理 dentry 和 inode优化减少不必要的 stat() 调用使用 openat() 相对路径复用已解析的 dentry避免深层目录结构4.3.inode 缓存优化# 查看 inode 缓存 cat/proc/slabinfo|grep inode # 文件系统挂载选项 mount-o noatime/dev/sda1/data # 禁用访问时间更新 mount-o relatime/dev/sda1/data # 相对时间更新推荐4.4.I/O 调度与异步 I/O技术说明io_uring现代异步 I/O零拷贝、批处理性能最佳AIO传统 POSIX AIO有诸多限制epoll O_NONBLOCK网络/文件事件驱动Direct I/O绕过页缓存O_DIRECT数据库常用// io_uring 示例简化structio_uringring;io_uring_queue_init(32,ring,0);structio_uring_sqe*sqeio_uring_get_sqe(ring);io_uring_prep_read(sqe,fd,buf,size,offset);io_uring_submit(ring);structio_uring_cqe*cqe;io_uring_wait_cqe(ring,cqe);// 处理完成io_uring_cqe_seen(ring,cqe);4.5.文件描述符优化# 查看进程 fd 限制 ulimit-n # 系统级限制 cat/proc/sys/fs/file-max # 系统最大打开文件数 cat/proc/sys/fs/nr_open # 单个进程最大 fd # 高并发场景调整 sysctl fs.file-max20971524.6.零拷贝技术传统方式磁盘 → 页缓存 → 用户缓冲区 → socket 缓冲区 → 网卡 ↑______内核空间______↑ ↑____用户空间____↑ ↑__内核__↑4次拷贝4次上下文切换 sendfile磁盘 → 页缓存 ────────────────→ socket 缓冲区 → 网卡2次拷贝DMA 引擎直接搬运2次上下文切换 splice 管道直接连接两个 fd完全在内核空间完成实例// sendfile 零拷贝sendfile(out_fd,in_fd,offset,count);// splice 零拷贝intpipefd[2];pipe(pipefd);splice(in_fd,off_in,pipefd[1],NULL,len,SPLICE_F_MOVE);splice(pipefd[0],NULL,out_fd,off_out,len,SPLICE_F_MOVE);4.7.调优检查清单层面检查项命令/配置内存页缓存命中率vmstat 1关注bi/boCPU软中断消耗cat /proc/softirqs磁盘I/O 调度器cat /sys/block/sda/queue/scheduler文件系统挂载选项noatime,nodiratime应用fd 泄漏ls /proc/pid/fd | wc -l网络零拷贝启用ethtool -k eth0查看tx-checksumming
返回列表