技术编程|低调的 Linux 文件系统家族( 三 )


在加锁阶段 , 进程需要设计好加锁失败后的情况 , 也就是判断加锁失败后是否选择阻塞 , 如果选择阻塞式 , 那么当已经加锁的进程中的锁被删除时 , 这个进程会解除阻塞并替换锁 。 如果进程选择非阻塞式的 , 那么就不会替换这个锁 , 会立刻从系统调用中返回 , 标记状态码表示是否加锁成功 , 然后进程会选择下一个时间再次尝试 。
加锁区域是可以重叠的 。 下面我们演示了三种不同条件的加锁区域 。

技术编程|低调的 Linux 文件系统家族
本文插图

如上图所示 , A 的共享锁在第四字节到第八字节进行加锁

技术编程|低调的 Linux 文件系统家族
本文插图

如上图所示 , 进程在 A 和 B 上同时加了共享锁 , 其中 6 - 8 字节是重叠锁

技术编程|低调的 Linux 文件系统家族
本文插图

如上图所示 , 进程 A 和 B 和 C 同时加了共享锁 , 那么第六字节和第七字节是共享锁 。
如果此时一个进程尝试在第 6 个字节处加锁 , 此时会设置失败并阻塞 , 由于该区域被 A B C 同时加锁 , 那么只有等到 A B C 都释放锁后 , 进程才能加锁成功 。
Linux 文件系统调用
许多系统调用都会和文件与文件系统有关 。 我们首先先看一下对单个文件的系统调用 , 然后再来看一下对整个目录和文件的系统调用 。
为了创建一个新的文件 , 会使用到 creat 方法 , 注意没有 e。
这里说一个小插曲 , 曾经有人问 UNIX 创始人 Ken Thompson , 如果有机会重新写 UNIX, 你会怎么办 , 他回答自己要把 creat 改成 create, 哈哈哈哈 。
?
这个系统调用的两个参数是文件名和保护模式
fd = creat("aaa",mode);
这段命令会创建一个名为 aaa 的文件 , 并根据 mode 设置文件的保护位 。 这些位决定了哪个用户可能访问文件、如何访问 。
creat 系统调用不仅仅创建了一个名为 aaa 的文件 , 还会打开这个文件 。 为了允许后续的系统调用访问这个文件 , 这个 creat 系统调用会返回一个 非负整数,这个就叫做 文件描述符(file deor), 也就是上面的 fd 。
如果在已经存在的文件上调用了 creat 系统调用 , 那么该文件中的内容会被清除 , 从 0 开始 。 通过设置合适的参数 ,open 系统调用也能够创建文件 。
下面让我们看一看主要的系统调用 , 如下表所示
系统调用描述fd = creat(name,mode)一种创建一个新文件的方式fd = open(file, ...)打开文件读、写或者读写s = close(fd)关闭一个打开的文件n = read(fd, buffer, nbytes)从文件中向缓存中读入数据n = write(fd, buffer, nbytes)从缓存中向文件中写入数据position = lseek(fd, offset, whence)移动文件指针s = stat(name, &buf)获取文件信息s = fstat(fd, &buf)获取文件信息s = pipe(&fd[0])创建一个管道s = fcntl(fd,...)文件加锁等其他操作
为了对一个文件进行读写的前提是先需要打开文件 , 必须使用 creat 或者 open 打开 , 参数是打开文件的方式 , 是只读、可读写还是只写 。 open 系统调用也会返回文件描述符 。 打开文件后 , 需要使用 close 系统调用进行关闭 。 close 和 open 返回的 fd 总是未被使用的最小数量 。
什么是文件描述符?文件描述符就是一个数字 , 这个数字标示了计算机操作系统中打开的文件 。 它描述了数据资源 , 以及访问资源的方式 。
?
当程序要求打开一个文件时 , 内核会进行如下操作
授予访问权限
在 全局文件表(global file table) 中创建一个 条目(entry)
向软件提供条目的位置


推荐阅读