linux 如何赋值目录,Linux文件系统之目录的建立
一:前言
在用戶空間中,建立目錄所用的API為mkdir().它在內(nèi)核中的系統(tǒng)調(diào)用入口是sys_mkdir().今天跟蹤一下
函數(shù)來分析linux文件系統(tǒng)中目錄的建立過程.
二:sys_mkdir()
Sys_mkdir()對應(yīng)的代碼如下:
asmlinkage long sys_mkdir(const char __user * pathname, int mode)
{
int error = 0;
char * tmp;
//把用戶空間的值copy到內(nèi)核空間
tmp = getname(pathname);
error = PTR_ERR(tmp);
if (!IS_ERR(tmp)) {
struct dentry *dentry;
struct nameidata nd;
//先查到它的父目錄,看父目錄是否存在
error = path_lookup(tmp, LOOKUP_PARENT, &nd);
if (error)
goto out;
//尋找子結(jié)點(diǎn)的dentry. 如果沒有,則新建之
dentry = lookup_create(&nd, 1);
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
if (!IS_POSIXACL(nd.dentry->d_inode))
mode &= ~current->fs->umask;
//與具體的文件系統(tǒng)相關(guān)的部份
error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
//減少dentry的引用計(jì)數(shù)
dput(dentry);
}
up(&nd.dentry->d_inode->i_sem);
//釋放臨時內(nèi)存
path_release(&nd);
out:
putname(tmp);
}
return error;
}
這個函數(shù)里面有幾個重要的子函數(shù). path_lookup()在前一篇文章中已經(jīng)分析過了.如果不太了解,請參閱相關(guān)的部份.
lookup_create()的代碼如下:
{
struct dentry *dentry;
//防止并發(fā)操作,獲得信號量
down(&nd->dentry->d_inode->i_sem);
dentry = ERR_PTR(-EEXIST);
//如果之前的查找過程失敗
if (nd->last_type != LAST_NORM)
goto fail;
//去掉LOOKUP_PARENT標(biāo)志
nd->flags &= ~LOOKUP_PARENT;
//在緩存中尋找相應(yīng)的dentry.如果沒有。則新建之
dentry = lookup_hash(&nd->last, nd->dentry);
//創(chuàng)建或者查找失敗
if (IS_ERR(dentry))
goto fail;
//如果不是建立一個目錄而且文件名字不是以0結(jié)尾
//出錯退出
if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
goto enoent;
return dentry;
enoent:
dput(dentry);
dentry = ERR_PTR(-ENOENT);
fail:
return dentry;
}
lookup_hash()à __lookup_hash():
static struct dentry * __lookup_hash(struct qstr *name, struct dentry * base, struct nameidata *nd)
{
struct dentry * dentry;
struct inode *inode;
int err;
inode = base->d_inode;
//檢查是否有相關(guān)的權(quán)限
err = permission(inode, MAY_EXEC, nd);
dentry = ERR_PTR(err);
if (err)
goto out;
/*
* See if the low-level filesystem might want
* to use its own hash..
*/
//如果自定義了hash計(jì)算
if (base->d_op && base->d_op->d_hash) {
err = base->d_op->d_hash(base, name);
dentry = ERR_PTR(err);
if (err < 0)
goto out;
}
//從緩存中尋找
dentry = cached_lookup(base, name, nd);
if (!dentry) {
//如果緩存中沒有相關(guān)項(xiàng)。則新建之
struct dentry *new = d_alloc(base, name);
dentry = ERR_PTR(-ENOMEM);
if (!new)
goto out;
//到具體的文件系統(tǒng)中查找
dentry = inode->i_op->lookup(inode, new, nd);
if (!dentry)
dentry = new;
else
dput(new);
}
out:
return dentry;
}
值得注意的是:經(jīng)過上述的操作,返回的dentry有可能是原本就存在的.對這種情況是怎么排除的呢?繼續(xù)看sys_mkdir()的另一個子函數(shù):
int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
//對異常情況的排除和權(quán)限的檢查
int error = may_create(dir, dentry, NULL);
if (error)
return error;
//如果父結(jié)點(diǎn)不允許mkdir操作
if (!dir->i_op || !dir->i_op->mkdir)
return -EPERM;
mode &= (S_IRWXUGO|S_ISVTX);
error = security_inode_mkdir(dir, dentry, mode);
if (error)
return error;
DQUOT_INIT(dir);
//調(diào)用父結(jié)點(diǎn)的mkdir操作
error = dir->i_op->mkdir(dir, dentry, mode);
if (!error) {
//如果成功,通告與之關(guān)聯(lián)的進(jìn)程
inode_dir_notify(dir, DN_CREATE);
security_inode_post_mkdir(dir,dentry, mode);
}
return error;
}
在這里看到,最終會調(diào)用父進(jìn)程的i_op.mkdir操作.另外,對于上面說的相應(yīng)結(jié)點(diǎn)已經(jīng)存在的情況是在may_create()中檢測的:
static inline int may_create(struct inode *dir, struct dentry *child,
struct nameidata *nd)
{
//如果欲建結(jié)點(diǎn)的inode已經(jīng)存在
//對于一個新建的dentry.其d_inode指向?yàn)榭?
if (child->d_inode)
return -EEXIST;
//判斷父目錄是否已經(jīng)失效
if (IS_DEADDIR(dir))
return -ENOENT;
//權(quán)限檢查
return permission(dir,MAY_WRITE | MAY_EXEC, nd);
}
Mkdir的大體架構(gòu)就如此了.下面討論一下rootfs和ext2中的目錄創(chuàng)建.
三:rootfs的目錄創(chuàng)建
在前一篇文章分析到.掛載rootfs時,對文件系統(tǒng)根目錄的inode.i_op賦值如下:
static 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,
};
對應(yīng)的mkdir操作入口是ramfs_mkdir():
static int ramfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
{
//創(chuàng)建結(jié)點(diǎn)
int retval = ramfs_mknod(dir, dentry, mode | S_IFDIR, 0);
//如果創(chuàng)建成功,更新i_nlink計(jì)數(shù)
if (!retval)
dir->i_nlink++;
return retval;
}
Ramsf_mknod()的代碼如下:
static int
ramfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
{
//在文件系統(tǒng)中分其為配一個inode
struct inode * inode = ramfs_get_inode(dir->i_sb, mode, dev);
int error = -ENOSPC;
if (inode) {
//如果分配成功
if (dir->i_mode & S_ISGID) {
inode->i_gid = dir->i_gid;
if (S_ISDIR(mode))
inode->i_mode |= S_ISGID;
}
//將dentry與分配的inode關(guān)聯(lián)起來
d_instantiate(dentry, inode);
//增加dentry的引用計(jì)數(shù)
dget(dentry); /* Extra count - pin the dentry in core */
error = 0;
}
return error;
}
這個函數(shù)中的子函數(shù)我們都在前面已經(jīng)分析過.請自行查閱本站的其它文檔.其操作非常簡單。就是分配一個inode。然后將inode 與dentry建立關(guān)聯(lián).因?yàn)閞ootfs是一個基于RAM的文件系統(tǒng)。其inode的分配就是在內(nèi)存中創(chuàng)建一個inode空間,然后為其各項(xiàng)操作賦值而已.
四:ext2中的目錄創(chuàng)建
經(jīng)過上一章的分析可以看到.ext2文件系統(tǒng)根目錄的inode.i_op被賦值為ext2_dir_inode_operations.其結(jié)構(gòu)如下所示:
struct inode_operations ext2_dir_inode_operations = {
.create?????? = ext2_create,
.lookup?????? = ext2_lookup,
.link???????? = ext2_link,
.unlink?????? = ext2_unlink,
.symlink = ext2_symlink,
.mkdir??????? = ext2_mkdir,
.rmdir??????? = ext2_rmdir,
.mknod??????? = ext2_mknod,
.rename?????? = ext2_rename,
#ifdef CONFIG_EXT2_FS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr??? = ext2_listxattr,
.removexattr? = generic_removexattr,
#endif
.setattr = ext2_setattr,
.permission?? = ext2_permission,
}
Mkdir對應(yīng)的入口為ext2_mkdir().代碼如下:
static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
{
struct inode * inode;
int err = -EMLINK;
if (dir->i_nlink >= EXT2_LINK_MAX)
goto out;
//增加dir的引用計(jì)數(shù),并將其置為"臟"
ext2_inc_count(dir);
//在文件系統(tǒng)中分配一個inode
inode = ext2_new_inode (dir, S_IFDIR | mode);
err = PTR_ERR(inode);
if (IS_ERR(inode))
goto out_dir;
//為inode的各項(xiàng)操作賦值
inode->i_op = &ext2_dir_inode_operations;
inode->i_fop = &ext2_dir_operations;
//為inode對應(yīng)的i_mapping賦值
if (test_opt(inode->i_sb, NOBH))
inode->i_mapping->a_ops = &ext2_nobh_aops;
else
inode->i_mapping->a_ops = &ext2_aops;
//增加inode的引用計(jì)數(shù),并將其置為"臟"
ext2_inc_count(inode);
//對目錄結(jié)點(diǎn)的初始化
err = ext2_make_empty(inode, dir);
if (err)
goto out_fail;
//更新父目錄,使inode加入父目錄
err = ext2_add_link(dentry, inode);
if (err)
goto out_fail;
//使dentry和inode建立關(guān)聯(lián)
d_instantiate(dentry, inode);
out:
return err;
out_fail:
ext2_dec_count(inode);
ext2_dec_count(inode);
iput(inode);
out_dir:
ext2_dec_count(dir);
goto out;
}
逐個分析上面所涉及到的子函數(shù).
在ext2中分配一個inode是由ext2_new_inode()完成的.它的代碼如下:
struct inode *ext2_new_inode(struct inode *dir, int mode)
{
struct super_block *sb;
struct buffer_head *bitmap_bh = NULL;
struct buffer_head *bh2;
int group, i;
ino_t ino = 0;
struct inode * inode;
struct ext2_group_desc *gdp;
struct ext2_super_block *es;
struct ext2_inode_info *ei;
struct ext2_sb_info *sbi;
int err;
sb = dir->i_sb;
//分配一個inode
inode = new_inode(sb);
if (!inode)
return ERR_PTR(-ENOMEM);
//inode的私有結(jié)構(gòu)
ei = EXT2_I(inode);
//super_block中的ext2私有結(jié)構(gòu)
sbi = EXT2_SB(sb);
//ext2的super_block
es = sbi->s_es;
//尋找一個合適的組來分配inode
if (S_ISDIR(mode)) {
if (test_opt(sb, OLDALLOC))
group = find_group_dir(sb, dir);
else
group = find_group_orlov(sb, dir);
} else
group = find_group_other(sb, dir);
if (group == -1) {
err = -ENOSPC;
goto fail;
}
//遍歷組描述符
for (i = 0; i < sbi->s_groups_count; i++) {
//group對應(yīng)的組開始遍歷
//取得組描述符
gdp = ext2_get_group_desc(sb, group, &bh2);
//釋放bitmap_bh.已經(jīng)后面會使用這個臨時變量
brelse(bitmap_bh);
//取得組描述符里的inode位圖
bitmap_bh = read_inode_bitmap(sb, group);
if (!bitmap_bh) {
err = -EIO;
goto fail;
}
ino = 0;
repeat_in_this_group:
//尋找位圖中第一個沒有使用的位
ino = ext2_find_next_zero_bit((unsigned long *)bitmap_bh->b_data,
EXT2_INODES_PER_GROUP(sb), ino);
//如果找到的位大于塊組中的inode數(shù).那從group之后的塊組中分配
if (ino >= EXT2_INODES_PER_GROUP(sb)) {
/*
* Rare race: find_group_xx() decided that there were
* free inodes in this group, but by the time we tried
* to allocate one, they're all gone.? This can also
* occur because the counters which find_group_orlov()
* uses are approximate.? So just go and search the
* next block group.
*/
//已經(jīng)到達(dá)塊組數(shù)目最大值。則將其置為零.然后重新循環(huán)
if (++group == sbi->s_groups_count)
group = 0;
continue;
}
//將inode 位圖中的分配位置位
if (ext2_set_bit_atomic(sb_bgl_lock(sbi, group),
ino, bitmap_bh->b_data)) {
/* we lost this inode */
//如果該位已經(jīng)被置位了.說明其它的內(nèi)核控制路徑將其分配了.
//那就找它的下一個沒有被使用的inode
//如果下一個超過了這個組中的最大inode數(shù)目。那從下一個塊組中分配
if (++ino >= EXT2_INODES_PER_GROUP(sb)) {
/* this group is exhausted, try next group */
if (++group == sbi->s_groups_count)
group = 0;
continue;
}
/* try to find free inode in the same group */
//重新從塊組中尋找沒有被使用的inode
goto repeat_in_this_group;
}
//如果運(yùn)行到這里的話,說明分配成功了
goto got;
}
/*
* Scanned all blockgroups.
*/
err = -ENOSPC;
goto fail;
got:
mark_buffer_dirty(bitmap_bh);
if (sb->s_flags & MS_SYNCHRONOUS)
sync_dirty_buffer(bitmap_bh);
brelse(bitmap_bh);
//將塊組中的inode序號轉(zhuǎn)換為全局inode計(jì)數(shù)
ino += group * EXT2_INODES_PER_GROUP(sb) + 1;
//如果inode序號小于super_block的超始inode序號或者大于inode總數(shù)
//出錯退出
if (ino < EXT2_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) {
ext2_error (sb, "ext2_new_inode",
"reserved inode or inode > inodes count - "
"block_group = %d,inode=%lu", group,
(unsigned long) ino);
err = -EIO;
goto fail;
}
//更新統(tǒng)計(jì)計(jì)數(shù)
percpu_counter_mod(&sbi->s_freeinodes_counter, -1);
if (S_ISDIR(mode))
percpu_counter_inc(&sbi->s_dirs_counter);
spin_lock(sb_bgl_lock(sbi, group));
gdp->bg_free_inodes_count =
cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) - 1);
//更新s_debts
if (S_ISDIR(mode)) {
if (sbi->s_debts[group] < 255)
sbi->s_debts[group]++;
gdp->bg_used_dirs_count =
cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) + 1);
} else {
if (sbi->s_debts[group])
sbi->s_debts[group]--;
}
spin_unlock(sb_bgl_lock(sbi, group));
sb->s_dirt = 1;
mark_buffer_dirty(bh2);
inode->i_uid = current->fsuid;
if (test_opt (sb, GRPID))
inode->i_gid = dir->i_gid;
else if (dir->i_mode & S_ISGID) {
inode->i_gid = dir->i_gid;
if (S_ISDIR(mode))
mode |= S_ISGID;
} else
inode->i_gid = current->fsgid;
inode->i_mode = mode;
//更新inode表示的索引結(jié)點(diǎn)號
inode->i_ino = ino;
inode->i_blksize = PAGE_SIZE;??? /* This is the optimal IO size (for stat), not the fs block size */
inode->i_blocks = 0;
//使i_mtine,i_atime,i_ctime置為當(dāng)前時間
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
memset(ei->i_data, 0, sizeof(ei->i_data));
ei->i_flags = EXT2_I(dir)->i_flags & ~EXT2_BTREE_FL;
if (S_ISLNK(mode))
ei->i_flags &= ~(EXT2_IMMUTABLE_FL|EXT2_APPEND_FL);
/* dirsync is only applied to directories */
if (!S_ISDIR(mode))
ei->i_flags &= ~EXT2_DIRSYNC_FL;
ei->i_faddr = 0;
ei->i_frag_no = 0;
ei->i_frag_size = 0;
ei->i_file_acl = 0;
ei->i_dir_acl = 0;
ei->i_dtime = 0;
ei->i_block_group = group;
ei->i_next_alloc_block = 0;
ei->i_next_alloc_goal = 0;
ei->i_prealloc_block = 0;
ei->i_prealloc_count = 0;
ei->i_dir_start_lookup = 0;
ei->i_state = EXT2_STATE_NEW;
ext2_set_inode_flags(inode);
spin_lock(&sbi->s_next_gen_lock);
inode->i_generation = sbi->s_next_generation++;
spin_unlock(&sbi->s_next_gen_lock);
insert_inode_hash(inode);
if (DQUOT_ALLOC_INODE(inode)) {
DQUOT_DROP(inode);
err = -ENOSPC;
goto fail2;
}
err = ext2_init_acl(inode, dir);
if (err) {
DQUOT_FREE_INODE(inode);
goto fail2;
}
//置inode為“臟”
mark_inode_dirty(inode);
ext2_debug("allocating inode %lu\n", inode->i_ino);
ext2_preread_inode(inode);
return inode;
fail2:
inode->i_flags |= S_NOQUOTA;
inode->i_nlink = 0;
iput(inode);
return ERR_PTR(err);
fail:
make_bad_inode(inode);
iput(inode);
return ERR_PTR(err);
}
查找一個末使用的索引結(jié)點(diǎn)有一個規(guī)則,就是盡量使每個塊組達(dá)到平衡.所以linux在ext2_sb_info結(jié)構(gòu)中加了一個s_debts字段.用來表示每個塊組中的文件與目錄的分配情況.計(jì)算的方法是在此find_group_orlov(目錄)和find_group_other(其它類型的文件)中完成的.
每個頁面都包含兩個特殊目錄結(jié)構(gòu) “.”和 “..”.單點(diǎn)代表其本身,雙點(diǎn)代表父目錄.這個過程是在ext2_make_empty()中完成的.對應(yīng)代碼如下:
int ext2_make_empty(struct inode *inode, struct inode *parent)
{
struct address_space *mapping = inode->i_mapping;
//找到頁面映射所代表的首個頁面
struct page *page = grab_cache_page(mapping, 0);
unsigned chunk_size = ext2_chunk_size(inode);
struct ext2_dir_entry_2 * de;
int err;
void *kaddr;
if (!page)
return -ENOMEM;
//先調(diào)用prepare_write().因?yàn)橹髸age寫到文件系統(tǒng)中去
err = mapping->a_ops->prepare_write(NULL, page, 0, chunk_size);
if (err) {
unlock_page(page);
goto fail;
}
//將page臨時映射到內(nèi)核
kaddr = kmap_atomic(page, KM_USER0);
//目錄中的第一個文件對象
de = (struct ext2_dir_entry_2 *)kaddr;
//每個目錄中都有兩個默認(rèn)存在的對象.和..
//將'.'加至目錄中,其inode結(jié)點(diǎn)號指向其本身
de->name_len = 1;
de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(1));
memcpy (de->name, ".\0\0", 4);
de->inode = cpu_to_le32(inode->i_ino);
ext2_set_de_type (de, inode);
//設(shè)置'..'.使其指向父目錄
de = (struct ext2_dir_entry_2 *)(kaddr + EXT2_DIR_REC_LEN(1));
de->name_len = 2;
de->rec_len = cpu_to_le16(chunk_size - EXT2_DIR_REC_LEN(1));
de->inode = cpu_to_le32(parent->i_ino);
memcpy (de->name, "..\0", 4);
ext2_set_de_type (de, inode);
//釋放掉映射區(qū)間
kunmap_atomic(kaddr, KM_USER0);
//將更改的頁面提交到文件系統(tǒng)
err = ext2_commit_chunk(page, 0, chunk_size);
fail:
//頁面使用完了,減少其使用計(jì)數(shù)
page_cache_release(page);
return err;
}
初始完成之后,要將子目錄插入父目錄所表的空間的。它是由ext2_add_link()完成的。代碼如下:
int ext2_add_link (struct dentry *dentry, struct inode *inode)
{
//得到父目錄的inode
struct inode *dir = dentry->d_parent->d_inode;
const char *name = dentry->d_name.name;
int namelen = dentry->d_name.len;
unsigned chunk_size = ext2_chunk_size(dir);
unsigned reclen = EXT2_DIR_REC_LEN(namelen);
unsigned short rec_len, name_len;
struct page *page = NULL;
ext2_dirent * de;
//父目錄結(jié)點(diǎn)大小所占的頁面數(shù)
unsigned long npages = dir_pages(dir);
unsigned long n;
char *kaddr;
unsigned from, to;
int err;
/*
* We take care of directory expansion in the same loop.
* This code plays outside i_size, so it locks the page
* to protect that region.
*/
//遍歷結(jié)點(diǎn)所在的空間
for (n = 0; n <= npages; n++) {
char *dir_end;
page = ext2_get_page(dir, n);
err = PTR_ERR(page);
if (IS_ERR(page))
goto out;
lock_page(page);
kaddr = page_address(page);
//本頁面的最后的位置.
//ext2_last_byte: 如果剩余的長度大于一個頁面,則返回一個頁面大小.否則返回剩余空間大小
dir_end = kaddr + ext2_last_byte(dir, n);
de = (ext2_dirent *)kaddr;
kaddr += PAGE_CACHE_SIZE - reclen;
while ((char *)de <= kaddr) {
//到了結(jié)點(diǎn)空間的末尾
if ((char *)de == dir_end) {
/* We hit i_size */
name_len = 0;
rec_len = chunk_size;
de->rec_len = cpu_to_le16(chunk_size);
de->inode = 0;
goto got_it;
}
//目錄中文件所占空間長度為0.非法
if (de->rec_len == 0) {
ext2_error(dir->i_sb, __FUNCTION__,
"zero-length directory entry");
err = -EIO;
goto out_unlock;
}
err = -EEXIST;
//在目錄所包含的文件中,含有同名的結(jié)點(diǎn)
if (ext2_match (namelen, name, de))
goto out_unlock;
name_len = EXT2_DIR_REC_LEN(de->name_len);
rec_len = le16_to_cpu(de->rec_len);
//de->inode==0.表示目錄中的此結(jié)點(diǎn)被刪除
//rec_len >= reclen:表示舊結(jié)點(diǎn)中有足夠的空間存儲新的結(jié)點(diǎn)
if (!de->inode && rec_len >= reclen)
goto got_it;
//這個結(jié)點(diǎn)中有空間剩余.(可能是它后面有節(jié)點(diǎn)被刪除造成的)
if (rec_len >= name_len + reclen)
goto got_it;
de = (ext2_dirent *) ((char *) de + rec_len);
}
unlock_page(page);
ext2_put_page(page);
}
BUG();
return -EINVAL;
got_it:
from = (char*)de - (char*)page_address(page);
to = from + rec_len;
err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
if (err)
goto out_unlock;
if (de->inode) {
//這是屬于結(jié)點(diǎn)空間有剩余的情況
//即在空間中插入一個新的結(jié)點(diǎn)
ext2_dirent *de1 = (ext2_dirent *) ((char *) de + name_len);
de1->rec_len = cpu_to_le16(rec_len - name_len);
de->rec_len = cpu_to_le16(name_len);
de = de1;
}
//對目錄的相關(guān)項(xiàng)進(jìn)行賦值
de->name_len = namelen;
memcpy (de->name, name, namelen);
de->inode = cpu_to_le32(inode->i_ino);
ext2_set_de_type (de, inode);
//提交所做的修改,將其寫入文件系統(tǒng)
err = ext2_commit_chunk(page, from, to);
//更改時間戳
dir->i_mtime = dir->i_ctime = CURRENT_TIME;
EXT2_I(dir)->i_flags &= ~EXT2_BTREE_FL;
mark_inode_dirty(dir);
/* OFFSET_CACHE */
out_put:
ext2_put_page(page);
out:
return err;
out_unlock:
unlock_page(page);
goto out_put;
}
在這里,忽略了頁面映射與文件系統(tǒng)驅(qū)動的交互過程。關(guān)于頁面緩存后續(xù)再給出章節(jié)進(jìn)行分析.
五:小結(jié)
在這一節(jié)里,以rootfs和ext2文件系統(tǒng)為例分析了目錄的建立過程.只要對ext2文件系統(tǒng)的相關(guān)部分有所了解.理解這部份代碼并不難.其中關(guān)于頁面緩存部份以后再給出專題分析.詳情請關(guān)注本站更新.
總結(jié)
以上是生活随笔為你收集整理的linux 如何赋值目录,Linux文件系统之目录的建立的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: tk域名怎么延期(tk域名注册不了)
- 下一篇: ubuntu系统虚拟机linux系统,基