上一节讲到挂在函数,这一节要讲创建文件夹,创建文件这些操作。刚刚浏览了一下代码,感觉代码量不大,可以分章节错了,不过上一篇确实讲的有点多,那这一篇就当做休息过渡。

3.1 创建文件夹

上一节讲过创建根目录的时候绑定了两类操作函数,我们来看看:

const struct file_operations simple_dir_operations = {
.open = dcache_dir_open,
.release = dcache_dir_close,
.llseek = dcache_dir_lseek,
.read = generic_read_dir,
.iterate = dcache_readdir,
.fsync = noop_fsync,
};

static const struct inode_operations ramfs_dir_inode_operations = {
.create = ramfs_create,
.lookup = simple_lookup,
.link = simple_link,
.unlink = simple_unlink,
.symlink = ramfs_symlink,
.mkdir = ramfs_mkdir,
.rmdir = simple_rmdir,
.mknod = ramfs_mknod,
.rename = simple_rename,
};

simple_dir_operations:这个是inode操作函数,因为这是个目录,所以inode操作的都是跟目录有关的,dcache是目录项对象缓存的机制。

所以说我们的创建文件夹的函数是ramfs_mkdir

static int ramfs_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode)
{
int retval = ramfs_mknod(dir, dentry, mode | S_IFDIR, 0);
if (!retval)
inc_nlink(dir); //创建文件需要硬连接计数加一
return retval;
}

在Unix系统中,我们发现文件夹其实也是一种文件,所以创建文件夹的函数是这样的:

static int ramfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl)
{
return ramfs_mknod(dir, dentry, mode | S_IFREG, 0);
}

我们来看一下真正的创建函数:

static int
ramfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
{
struct inode * inode = ramfs_get_inode(dir->i_sb, dir, mode, dev);
int error = -ENOSPC;

if (inode) {
d_instantiate(dentry, inode);
dget(dentry); /* Extra count - pin the dentry in core */
error = 0;
dir->i_mtime = dir->i_ctime = CURRENT_TIME;
}
return error;
}

ramfs_get_inode函数上一节刚讲,这里就不贴出代码了,内容可以讲述一下,就是创建了一个inode节点,这个结点链接到sb的s_inodes链表中,d_instantiate函数上节分析过,只要的作用就是把dentry中的d_inode节点指向inode节点,完成链接。

是不是讲到这里有点不通,就是参数的dir和dentry怎么来的,文件目录时怎么搜索的,这些是在内核中实现了,下一节课分析,这一节就相当于过一过。

3.2 软连接

在说一个软连接的函数,其他函数还是等下一节把整体框架捋清楚了之后,自然会明白了。

static int ramfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
{
struct inode *inode;
int error = -ENOSPC;

inode = ramfs_get_inode(dir->i_sb, dir, S_IFLNK|S_IRWXUGO, 0);
if (inode) {
int l = strlen(symname)+1;
error = page_symlink(inode, symname, l);
if (!error) {
d_instantiate(dentry, inode);
dget(dentry);
dir->i_mtime = dir->i_ctime = CURRENT_TIME;
} else
iput(inode);
}
return error;
}

创建软连接函数也比较简单,也是创建一个inode结点,然后再dentry的d_inode指向inode。

算了,不说了,这一节确实讲的不靠谱,因为都不知道传参的怎么来的,文件是怎么访问的,我们下一节见分晓。