用户打开文件期间修改inode中文件权限的相关技术问题
打开文件权限变更相关问题解答
当用户成功打开文件获得文件描述符后,系统仅在
open调用的瞬间做一次基于当前用户身份、文件inode权限的全量校验。后续即便文件权限被修改、甚至文件属主变更,只要进程持有该打开的文件描述符,就可以继续执行打开时被允许的操作,不会被新的权限规则拦截。
系统是否会在每次IO操作时持续做权限校验?
不会每次IO都重新基于inode做全量用户权限校验,实际逻辑非常清晰:
- 当
open调用权限校验通过后,内核会在代表该打开实例的文件结构体中,直接记录当前文件句柄允许的操作模式(对应open时传入的O_RDONLY/O_WRONLY/O_RDWR等访问标记)。 - 后续进程调用
read/write/ftruncate等操作文件的系统调用时,内核只会直接检查当前请求的操作是否在该句柄记录的允许范围内,不会再重新读取inode上存储的权限位、也不会再校验当前进程的uid/gid是否对文件有对应权限。 - 举个最直观的例子:如果进程以
O_RDONLY只读模式打开文件,哪怕后续把文件权限改成777、进程自身切换为文件属主,直接拿这个只读fd调用write依然会返回EBADF错误(错误的文件描述符),因为句柄创建时就没授予写权限,连inode权限校验环节都走不到;反过来,如果进程是以读写模式打开的文件,后续哪怕把文件权限改成000、把进程切换成其他无权限的普通用户,拿这个fd读写文件也会正常成功。
修改文件权限时,系统优先更新内存inode还是磁盘inode?
所有文件元数据(包括权限、属主、时间戳、文件大小等)的修改,永远优先更新内存中的inode缓存副本,绝对不会跳过缓存直接操作磁盘上的inode,核心逻辑如下:
- 所有运行中的进程访问文件时,第一步都是先查询内存中的inode缓存,如果缓存命中就不会发起磁盘IO读取inode。如果修改权限时直接写磁盘上的inode,内存中缓存的旧副本不会自动同步更新,其他进程访问文件时看到的还是旧权限,完全不符合权限修改即时生效的基本预期。
- 实际执行流程是:运行
chmod/chown等元数据修改命令时,如果目标inode还没加载到内存缓存,内核会先把磁盘上的inode完整读到内存;修改完内存中inode的对应字段后,会把该inode标记为「脏」状态,之后由内核的后台回写机制异步把脏的inode数据刷到磁盘做持久化存储,整个过程不需要调用方等待磁盘IO完成。 - 这也是为什么权限修改可以立刻对所有进程生效——所有进程访问文件时读取的都是已经更新完成的内存inode,完全不需要等磁盘回写动作结束。
内容的提问来源于stack exchange,提问作者Ariel Yael
相关产品推荐
相关产品推荐

