mkfifo
是一个用于创建有名管道的系统调用,其原型定义在 <sys/stat.h>
头文件中。
int mkfifo(const char *pathname, mode_t mode);
它的参数含义如下:
-
pathname
:是有名管道的路径名,即在文件系统中的名称。你可以指定相对路径或者绝对路径。例如,如果你要在当前目录下创建一个名为my_pipe
的有名管道,可以直接写"my_pipe"
。如果要指定路径,可以写"path/to/my_pipe"
。 -
mode
:是用于指定管道的权限的参数。它是一个八进制数,表示文件的权限掩码。通常使用的是文件权限位掩码,如0666
。在这里,0666
表示管道的权限为读写权限,所有用户都有权限读取和写入管道。具体的权限说明如下:0
:没有权限1
:执行权限2
:写入权限4
:读取权限
例如,0666
表示拥有读取(4)、写入(2)和执行(1)权限的用户都可以读取和写入管道。
mkfifo
的作用是创建一个具有指定路径和权限的有名管道。有名管道可以通过文件系统的路径名来访问,因此可以用于不同进程之间的通信。
在 Linux 系统中,mkfifo
函数是一个系统调用,它的底层实现是由操作系统内核提供的。
mkfifo
函数的底层实现可以简单地描述为以下步骤:
-
创建管道节点:在文件系统中创建一个特殊的文件节点,该节点用于表示有名管道。这个文件节点在文件系统中有一个路径名,可以像普通文件一样进行访问。这个文件节点的类型是 FIFO,即先进先出,用于实现管道的特性。
-
设置权限:根据传入的第二个参数,设置管道节点的权限。这个参数表示管道的读写权限,通常是一个八进制数,如
0666
。这决定了哪些用户可以访问管道,以及他们的访问权限是什么。 -
返回结果:将管道节点的信息返回给调用进程,以便后续对管道进行读写操作。
至于为什么要传入这两个参数:
-
pathname
参数是用来指定管道的路径名,即在文件系统中的名称。有名管道通过路径名来访问,因此需要指定管道的路径。这个参数决定了在文件系统中管道的位置。 -
mode
参数是用来指定管道的权限的参数。它决定了管道在文件系统中的访问权限,即哪些用户可以读取和写入管道。这个参数决定了谁可以访问管道以及他们的权限是什么。
下面是一个简化版的示例代码,演示了如何在 Linux 下实现 mkfifo
的底层逻辑。这个示例代码并不包含错误处理,只展示了核心逻辑。
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>int my_mkfifo(const char *pathname, mode_t mode) {
// 创建一个特殊的文件节点,并设置权限
int ret = mknod(pathname, S_IFIFO | mode, 0);
return ret;
}int main() {
// 调用自定义的 my_mkfifo 函数创建有名管道
my_mkfifo("my_pipe", 0666);
return 0;
}
实际上 mkfifo
函数可能会在底层调用更多的系统调用和内核函数来实现更复杂的逻辑,包括错误处理、文件系统相关操作等。上面的代码只是一个简化的示例,演示了 mkfifo
的基本原理。
本质上 mkfifo
函数的实现可以通过调用 mknod
来创建有名管道。在底层,mknod
函数用于创建各种类型的文件节点,包括普通文件、字符设备文件、块设备文件和 FIFO(有名管道)。
mknod
函数的原型定义在 <sys/stat.h>
头文件中,其声明如下:
int mknod(const char *pathname, mode_t mode, dev_t dev);
而mknod 的底层实现,可以参考 Linux 内核源代码,找到相应文件系统的实现。
在 Linux 内核源代码中,mknod
的底层实现在不同的文件系统中可能有所不同。以下是一个示例,展示了如何在 Ext4 文件系统中实现 mknod
函数的部分逻辑,依旧不包含错误处理:
int ext4_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev)
{
struct inode *inode;/* 创建新的 inode */
inode = ext4_new_inode(dir, mode, &dentry->d_name);/* 设置 inode 的设备号 */
inode->i_rdev = rdev;/* 将 inode 添加到目录中 */
d_instantiate(dentry, inode);
ext4_add_entry(dir, dentry);/* 更新目录的时间戳 */
ext4_update_dx_flag(dir);
ext4_mark_inode_dirty(dir);return 0;
}
ext4_new_inode
函数是 Ext4 文件系统中用于创建新 inode 的函数之一。它的作用是根据给定的目录 inode、文件模式和文件名创建一个新的 inode,并将其链接到文件系统中。
以下是一个简化的示例,展示了 ext4_new_inode
函数的大致实现:
struct inode *ext4_new_inode(struct inode *dir, umode_t mode, const struct qstr *qstr)
{
struct inode *inode;
struct super_block *sb = dir->i_sb;/* 为新 inode 分配内存 */
inode = new_inode(sb);
if (!inode)
return ERR_PTR(-ENOMEM);/* 初始化 inode 的基本属性 */
inode_init_owner(inode, dir, mode);
inode->i_size = 0;
inode->i_blocks = 0;/* 设置 inode 的文件模式 */
inode->i_mode = mode;/* 将 inode 添加到目录中 */
d_instantiate(dentry, inode);
inode_inc_link_count(inode);/* 将 inode 标记为脏 inode */
mark_inode_dirty(inode);return inode;
}
所以总结 mkfifo底层做了什么处理?
mkfifo
函数的底层实现主要涉及以下几个步骤:
-
参数验证: 首先,内核会对传入的参数进行验证,确保路径名和权限参数的有效性。
-
创建文件节点: 接着,内核会调用相应的文件系统的实现来创建一个特殊的文件节点,即有名管道。在创建过程中,可能会分配相应的内存空间,并初始化相关的数据结构。
-
设置权限和属性: 创建文件节点后,内核会根据传入的权限参数设置新创建的文件节点的权限和属性,包括读、写和执行权限等。
-
返回结果: 最后,内核会返回一个表示创建结果的值,通常是一个文件描述符或错误码。如果创建成功,会返回一个文件描述符,用于后续对管道的读写操作;如果创建失败,则返回一个错误码,表示失败的原因。
mkfifo
函数的底层实现主要是通过操作系统内核提供的文件系统接口来创建一个特殊的文件节点,然后设置其权限和属性,最终返回一个结果表示创建的状态。