// linux/fs/open.c
int sys_open(const char* filename, int flag)
{
i=open_namei(filename,flag,&inode);
// ...
}
int open_namei(...)
{
dir=dir_namei(pathname,&namelen,&basename);
static struct m_inode *dir_namei()
{ dir=get_dir(pathname); }
static struct m_inode *get_dir(const char *pathname)
{
if((c=get_fs_byte(pathname))==‘/’){
inode=current->root;
pathname++;
}
else if(c) inode=current->pwd;
while(1){ //函数的正确出口
if(!c) return inode;
bh=find_entry(&inode,thisname,namelen,&de);
int inr=de->inode;
int idev=inode->i_dev;
inode=iget(idev,inr); //根据目录项读取下一层inode
}
// ...
}
从根目录开始解析
void init(void)
{
setup((void *) &drive_info);
// ...
// kernel/hd.c
sys_setup(void * BIOS)
{
hd_info[drive].head = *(2+BIOS);
hd_info[drive].sect = *(14+BIOS);
mount_root();
...
}
// fs/super.c
void mount_root(void)
{
mi=iget(ROOT_DEV,ROOT_INO));
current->root = mi;
}
读取inode
struct m_inode * iget(int dev, int nr)
{
struct m_inode *inode = get_empty_inode();
inode->i_dev=dev; inode->i_num=nr;
read_inode(inode); return inode;
}
static void read_inode(struct m_inode *inode)
{
struct super_block *sb=get_super(inode->i_dev);
lock_inode(inode);
block=2+sb->s_imap_blocks+sb->s_zmap_blocks+
(inode->i_num-1)/INODES_PER_BLOCK;
bh=bread(inode->i_dev,block);
inode=bh->data[(inode->i_num-1)%INODES_PER_BLOCK];
unlock_inode(inode);
}
开始目录解析
struct dir_entry
{
unsigned short inode; //i节点号
char name[NAME_LEN]; //文件名
}
// fs/namei.c
static struct buffer_head *find_entry(struct m_inode **dir,
char *name, ..., struct dir_entry ** res_dir)
{
int entries=(*dir)->i_size/(sizeof(struct dir_entry));
int block=(*dir)->i_zone[0];
*bh=bread((*dir)->i_dev, block);
struct dir_entry *de =bh->b_data;
while(i<entries) {
if((char*)de>=BLOCK_SIZE+bh->b_data){
brelse(bh);
block=bmap(*dir,i/DIR_ENTRIES_PER_BLOCK);
bh=bread((*dir)->i_dev,block);
de=(struct dir_entry*)bh->b_data;
} //读入下一块上的目录项继续match
if(match(namelen,name,de)){
*res_dir=de;
return bh;
}
de++;
i++;
}
}