最簡單linux文件系統源碼 開源

開源開源開源

頭文件

#define MAXLEN 8

#define MAX_FILES 32

#define MAX_BLOCKSIZE 512

// 定義每一個目錄項的格式

struct dir_entry

{

char filename[MAXLEN];

uint8_t idx;

};

// 定義每一個文件的格式。

struct file_blk

{

uint8_t busy;

mode_t mode;

uint8_t idx;

union

{

uint8_t file_size;

uint8_t dir_children;

};

struct dir_entry data0[6];

char data[100];

};

源碼

#include <linux>

#include <linux>

#include <linux>

#include <linux>

#include "tinyFs.h"

#define CURRENT_TIME (current_kernel_time())

struct file_blk block[MAX_FILES+1];

int curr_count = 0;// 我勒個去,竟然使用了全局變量!

// 獲得一個尚未使用的文件塊,保存新創建的文件或者目錄

static int get_block(void)

{

int i;

// 就是一個遍歷,但實現快速。

for (i =2;i

{

if(!block[i].busy)

{

memset(&block[i],0,sizeof(struct file_blk));

block[i].busy =1;

return i;

}

}

return -1;

}

static struct inode_operations tinyfs_inode_ops ;

// 讀取目錄的實現

static int tinyfs_readdir(struct file *filp, struct dir_context *ctx)

{

//return -EISDIR;

#if 1

loff_t pos;

struct file_blk *blk;

struct dir_entry *entry;

int i;

pos = filp->f_pos;

if(pos)

return 0;

blk =(struct file_blk *)filp->f_path.dentry->d_inode->i_private;

if(!S_ISDIR(blk->mode))

{

return -ENOTDIR;

}

// 循環獲取一個目錄的所有文件的文件名

dir_emit_dot(filp, ctx);

ctx->pos++;

dir_emit_dotdot(filp, ctx);

ctx->pos++;

entry =(struct dir_entry *)&blk->data0;

for (i = 0; i < blk->dir_children; i++)

{

//filldir(dirent, entry[i].filename, MAXLEN, pos, entry[i].idx,DT_UNKNOWN);

if(!dir_emit(ctx, entry[i].filename, MAXLEN,entry[i].idx, DT_UNKNOWN))

break;

ctx->pos++;

//filp->f_pos += sizeof(struct dir_entry);

// pos += sizeof(struct dir_entry);

}

return 0;

#endif

}

// read實現

ssize_t tinyfs_read(struct file * filp, char __user * buf, size_t len, loff_t *ppos)

{

struct file_blk *blk;

char *buffer;

blk = (struct file_blk *)filp->f_path.dentry->d_inode->i_private;

if(*ppos >= blk->file_size)

return 0;

buffer = (char *)&blk->data[0];

len = min((size_t) blk->file_size, len);

if (copy_to_user(buf, buffer, len)) {

return -EFAULT;

}

*ppos += len;

return len;

}

// write實現

ssize_t tinyfs_write(struct file * filp, const char __user * buf, size_t len, loff_t* ppos)

{

struct file_blk *blk;

char *buffer;

blk = filp->f_path.dentry->d_inode->i_private;

buffer =(char*)&blk->data[0];

buffer += *ppos;

if (copy_from_user(buffer, buf, len))

{

return -EFAULT;

}

*ppos += len;

blk->file_size = *ppos;

return len;

}

const struct file_operations tinyfs_file_operations = {

.read = tinyfs_read,

.write = tinyfs_write,

};

const struct file_operations tinyfs_dir_operations = {

.owner = THIS_MODULE,

.iterate = tinyfs_readdir,

};

// 創建文件的實現

static int tinyfs_do_create(struct inode *dir, struct dentry *dentry, umode_t mode)

{

struct inode *inode;

struct super_block *sb;

struct dir_entry *entry;

struct file_blk *blk, *pblk;

int idx;

sb = dir->i_sb;

if (curr_count >= MAX_FILES)

{

return -ENOSPC;

}

if (!S_ISDIR(mode) && !S_ISREG(mode))

{

return -EINVAL;

}

inode = new_inode(sb);

if (!inode){

return -ENOMEM;

}

inode->i_sb = sb;

inode->i_op = &tinyfs_inode_ops;

inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;

idx = get_block();

// 獲取一個空閒的文件塊保存新文件

blk = &block[idx];

inode->i_ino =idx;

blk->mode = mode;

curr_count ++;

if (S_ISDIR(mode))

{

blk->dir_children = 0;

inode->i_fop = &tinyfs_dir_operations;

}

else if(S_ISREG(mode)) {

blk->file_size = 0;

inode->i_fop = &tinyfs_file_operations;

}

inode->i_private = blk;

pblk = (struct file_blk *)dir->i_private;

entry = (struct dir_entry *)&pblk->data0;

entry += pblk->dir_children;

pblk->dir_children ++;

entry->idx = idx;

memset(entry->filename, 0, MAXLEN);

strcpy(entry->filename, dentry->d_name.name);

// VFS穿針引線的關鍵步驟,將VFS的inode鏈接到鏈表

inode_init_owner(inode, dir, mode);

d_add(dentry, inode);

return 0;

}

static int tinyfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)

{

return tinyfs_do_create(dir, dentry, S_IFDIR | mode);

}

static int tinyfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl)

{

return tinyfs_do_create(dir, dentry, mode);

}

static struct inode *tinyfs_iget(struct super_block *sb, int idx)

{

struct inode *inode;

struct file_blk *blk;

inode = new_inode(sb);

inode->i_ino = idx;

inode->i_sb = sb;

inode->i_op = &tinyfs_inode_ops;

blk = &block[idx];

if (S_ISDIR(blk->mode))

inode->i_fop = &tinyfs_dir_operations;

else if (S_ISREG(blk->mode))

inode->i_fop = &tinyfs_file_operations;

inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;

inode->i_private = blk;

return inode;

}

struct dentry *tinyfs_lookup(struct inode *parent_inode, struct dentry *

child_dentry, unsigned int flags)

{

struct super_block *sb = parent_inode->i_sb;

struct file_blk *blk;

struct dir_entry *entry;

int i;

blk = (struct file_blk *)parent_inode->i_private;

entry =(struct dir_entry *)&blk->data[0];

for(i =0; i < blk->dir_children; i++)

{

if (!strcmp(entry[i].filename, child_dentry->d_name.name))

{

struct inode *inode = tinyfs_iget(sb, entry[i].idx);

struct file_blk *inner = (struct file_blk *)inode->i_private;

inode_init_owner(inode, parent_inode, inner->mode);

d_add(child_dentry, inode);

return NULL;

}

}

return NULL;

}

int tinyfs_rmdir(struct inode *dir, struct dentry *dentry)

{

#if 0

struct inode *inode = dentry->d_inode;

struct file_blk *blk = (struct file_blk *)inode->i_private;

memset(blk, 0, sizeof(struct file_blk));

blk->busy = 0;

#endif

int i;

struct inode *inode = dentry->d_inode;

struct file_blk *blk = (struct file_blk *)inode->i_private;

struct file_blk *pblk = (struct file_blk *)dir->i_private;

struct dir_entry *entry;

// 更新其上層目錄

entry = (struct dir_entry *)&pblk->data0;

for (i = 0; i < pblk->dir_children; i++)

{

if (!strcmp(entry[i].filename, dentry->d_name.name))

{

int j;

for (j = i; j < pblk->dir_children - 1; j++)

{

memcpy(&entry[j], &entry[j+1], sizeof(struct dir_entry));

}

pblk->dir_children --;

break;

}

}

blk->busy = 0;

return simple_rmdir(dir, dentry);

}

int tinyfs_unlink(struct inode *dir, struct dentry *dentry)

{

int i;

struct inode *inode = dentry->d_inode;

struct file_blk *blk = (struct file_blk *)inode->i_private;

struct file_blk *pblk = (struct file_blk *)dir->i_private;

struct dir_entry *entry;

// 更新其上層目錄

entry = (struct dir_entry *)&pblk->data0;

for (i = 0; i < pblk->dir_children; i++)

{

if (!strcmp(entry[i].filename, dentry->d_name.name))

{

int j;

for (j = i; j < pblk->dir_children - 1; j++)

{

memcpy(&entry[j], &entry[j+1], sizeof(struct dir_entry));

}

pblk->dir_children --;

break;

}

}

blk->busy = 0;

return simple_unlink(dir, dentry);

}

static struct inode_operations tinyfs_inode_ops = {

.create = tinyfs_create,

.lookup = tinyfs_lookup,

.mkdir = tinyfs_mkdir,

.rmdir = tinyfs_rmdir,

.unlink = tinyfs_unlink,

};

int tinyfs_fill_super(struct super_block *sb, void *data, int silent)

{

struct inode *root_inode;

int mode = S_IFDIR;

root_inode = new_inode(sb);

root_inode->i_ino = 1;

inode_init_owner(root_inode, NULL, mode);

root_inode->i_sb = sb;

root_inode->i_op = &tinyfs_inode_ops;

root_inode->i_fop = &tinyfs_dir_operations;

root_inode->i_atime = root_inode->i_mtime = root_inode->i_ctime =CURRENT_TIME;

block[1].mode = mode;

block[1].dir_children = 0;

block[1].idx = 1;

block[1].busy = 1;

root_inode->i_private = &block[1];

sb->s_root = d_make_root(root_inode);

curr_count ++;

return 0;

}

static struct dentry *tinyfs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data)

{

return mount_nodev(fs_type, flags, data, tinyfs_fill_super);

}

static void tinyfs_kill_superblock(struct super_block *sb)

{

kill_anon_super(sb);

}

struct file_system_type tinyfs_fs_type = {

.owner = THIS_MODULE,

.name = "tinyfs",

.mount = tinyfs_mount,

.kill_sb = tinyfs_kill_superblock,

};

static int tinyfs_init(void)

{

int ret;

memset(block, 0, sizeof(block));

ret = register_filesystem(&tinyfs_fs_type);

if (ret)

printk("register tinyfs failed\\n");

return ret;

}

static void tinyfs_exit(void)

{

unregister_filesystem(&tinyfs_fs_type);

}

module_init(tinyfs_init);

module_exit(tinyfs_exit);

MODULE_LICENSE("GPL");

"


分享到:


相關文章: