⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inode.c

📁 Linux0.01内核分析与操作系统设计 随书源代码
💻 C
字号:
#include <string.h>

#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <asm/system.h>

struct m_inode inode_table[NR_INODE]={{0,},};

static void read_inode(struct m_inode * inode);
static void write_inode(struct m_inode * inode);

static inline void wait_on_inode(struct m_inode * inode)
{
    cli();
    while (inode->i_lock)
        sleep_on(&inode->i_wait);	//在sched.c中定义
    sti();
}

static inline void lock_inode(struct m_inode * inode)
{
    cli();
    while (inode->i_lock)
        sleep_on(&inode->i_wait);
    inode->i_lock=1;
    sti();
}

static inline void unlock_inode(struct m_inode * inode)
{
    inode->i_lock=0;
    wake_up(&inode->i_wait);				//在sched.c中定义
}

void sync_inodes(void)
{
    int i;
    struct m_inode * inode;

    inode = 0+inode_table;
    for(i=0 ; i<NR_INODE ; i++,inode++) {
        wait_on_inode(inode);
        if (inode->i_dirt && !inode->i_pipe)
            write_inode(inode);
    }
}

static int _bmap(struct m_inode * inode,int block,int create)		//文件的硬盘映射
{
    struct buffer_head * bh;
    int i;

    if (block<0)
        panic("_bmap: block<0");
    if (block >= 7+512+512*512)			//此块是否超过了最大的文件影像所表示的块
        panic("_bmap: block>big");
    if (block<7) {
        if (create && !inode->i_zone[block])	//如果是要创建,并且该直接块是null的
            if (inode->i_zone[block]=new_block(inode->i_dev)) {	//建立新块,将找到的块放入i_zone中
                inode->i_ctime=CURRENT_TIME;		//修改时间
                inode->i_dirt=1;				//要求写盘
            }
        return inode->i_zone[block];
    }
    block -= 7;
    if (block<512) {				//如果此块位于一级间接块
        if (create && !inode->i_zone[7])
            if (inode->i_zone[7]=new_block(inode->i_dev)) {
                inode->i_dirt=1;
                inode->i_ctime=CURRENT_TIME;
            }
        if (!inode->i_zone[7])
            return 0;
        if (!(bh = bread(inode->i_dev,inode->i_zone[7])))	//将一级间接块读入缓冲区
            return 0;
        i = ((unsigned short *) (bh->b_data))[block];	//在一级间接块数据区中找到相应块号
        if (create && !i)
            if (i=new_block(inode->i_dev)) {
                ((unsigned short *) (bh->b_data))[block]=i;	//将找到的实际块写入一级间接块数据区
                bh->b_dirt=1;
            }
        brelse(bh);
        return i;
    }
    block -= 512;			//如果是二级间接块
    if (create && !inode->i_zone[8])
        if (inode->i_zone[8]=new_block(inode->i_dev)) {
            inode->i_dirt=1;
            inode->i_ctime=CURRENT_TIME;
        }
    if (!inode->i_zone[8])
        return 0;
    if (!(bh=bread(inode->i_dev,inode->i_zone[8])))
        return 0;
    i = ((unsigned short *)bh->b_data)[block>>9];
    if (create && !i)
        if (i=new_block(inode->i_dev)) {
            ((unsigned short *) (bh->b_data))[block>>9]=i;
            bh->b_dirt=1;
        }
    brelse(bh);
    if (!i)
        return 0;
    if (!(bh=bread(inode->i_dev,i)))
        return 0;
    i = ((unsigned short *)bh->b_data)[block&511];
    if (create && !i)
        if (i=new_block(inode->i_dev)) {
            ((unsigned short *) (bh->b_data))[block&511]=i;
            bh->b_dirt=1;
        }
    brelse(bh);
    return i;
}

int bmap(struct m_inode * inode,int block)
{
    return _bmap(inode,block,0);
}

int create_block(struct m_inode * inode, int block)
{
    return _bmap(inode,block,1);
}

void iput(struct m_inode * inode)		//释放该节点及该节点使用的所有块(在内存map中)
{
    if (!inode)
        return;
    wait_on_inode(inode);
    if (!inode->i_count)
        panic("iput: trying to free free inode");
    if (inode->i_pipe) {			//如果该节点是一个管道
        wake_up(&inode->i_wait);
        if (--inode->i_count)	//如果此节点是共享的,直接返回
            return;
        free_page(inode->i_size);	//如果没有进程用此节点,释放该页
        inode->i_count=0;
        inode->i_dirt=0;
        inode->i_pipe=0;
        return;
    }
    if (!inode->i_dev || inode->i_count>1) {
        inode->i_count--;
        return;
    }
repeat:
    if (!inode->i_nlinks) {
        truncate(inode);		//释放此节点的所有直接和间接块的map
        free_inode(inode);		//在s_imap表中清除该节点
        return;
    }
    if (inode->i_dirt) {
        write_inode(inode);	/* we can sleep - so do again */
        wait_on_inode(inode);
        goto repeat;
    }
    inode->i_count--;
    return;
}

static volatile int last_allocated_inode = 0;

struct m_inode * get_empty_inode(void)
{
    struct m_inode * inode;
    int inr;

    while (1) {
        inode = NULL;
        inr = last_allocated_inode;
        do {						//这个循环是在inode_table中取得一个内存节点
            if (!inode_table[inr].i_count) {
                inode = inr + inode_table;
                break;
            }
            inr++;
            if (inr>=NR_INODE)
                inr=0;
        } while (inr != last_allocated_inode);
        if (!inode) {					//如果节点为空,那么出错
            for (inr=0 ; inr<NR_INODE ; inr++)
                printk("%04x: %6d\t",inode_table[inr].i_dev,
                       inode_table[inr].i_num);
            panic("No free inodes in mem");
        }
        last_allocated_inode = inr;
        wait_on_inode(inode);
        while (inode->i_dirt) {			//如果节点是脏的,那么写盘
            write_inode(inode);
            wait_on_inode(inode);
        }
        if (!inode->i_count)
            break;
    }
    memset(inode,0,sizeof(*inode));			//将此节点初始化为0
    inode->i_count = 1;					//标记已分配
    return inode;
}

struct m_inode * get_pipe_inode(void)
{
    struct m_inode * inode;

    if (!(inode = get_empty_inode()))			//为管道取一个空的节点
        return NULL;
    if (!(inode->i_size=get_free_page())) {		//为这个节点分配内存
        inode->i_count = 0;
        return NULL;
    }
    inode->i_count = 2;	/* sum of readers/writers */
    PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;	//初始化管道为0
    inode->i_pipe = 1;					//标记该节点是一个管道
    return inode;
}

struct m_inode * iget(int dev,int nr)
{
    struct m_inode * inode, * empty;

    if (!dev)
        panic("iget with dev==0");
    empty = get_empty_inode();				//取一个空闲的内存节点
    inode = inode_table;					//inode指向inode_table[0]
    while (inode < NR_INODE+inode_table) {
        if (inode->i_dev != dev || inode->i_num != nr) {	//寻找是否有dev和nr的内存节点
            inode++;
            continue;
        }
        wait_on_inode(inode);			//等待释放此节点
        if (inode->i_dev != dev || inode->i_num != nr) {
            inode = inode_table;
            continue;
        }
        inode->i_count++;
        if (empty)
            iput(empty);
        return inode;
    }
    //以下代码是如果在当前的inode_table中没有现成的,所要执行的
    if (!empty)
        return (NULL);
    inode=empty;
    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;
    struct buffer_head * bh;
    int block;

    lock_inode(inode);
    sb=get_super(inode->i_dev);				//取得相应的i_dev所在的超级块
    block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks +
            (inode->i_num-1)/INODES_PER_BLOCK;		//计算出块号
    if (!(bh=bread(inode->i_dev,block)))
        panic("unable to read i-node block");	//读取节点所在的块进入buffer
    *(struct d_inode *)inode =
        ((struct d_inode *)bh->b_data)
        [(inode->i_num-1)%INODES_PER_BLOCK];	//计算出该节点在这个块的位移
    brelse(bh);
    unlock_inode(inode);
}

static void write_inode(struct m_inode * inode)
{
    struct super_block * sb;
    struct buffer_head * bh;
    int block;

    lock_inode(inode);
    sb=get_super(inode->i_dev);				//get_super在fs.h中定义
    block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks +
            (inode->i_num-1)/INODES_PER_BLOCK;
    if (!(bh=bread(inode->i_dev,block)))
        panic("unable to read i-node block");
    ((struct d_inode *)bh->b_data)
    [(inode->i_num-1)%INODES_PER_BLOCK] =
        *(struct d_inode *)inode;
    bh->b_dirt=1;
    inode->i_dirt=0;
    brelse(bh);
    unlock_inode(inode);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -