Chinaunix首页 | 论坛 | 博客
  • 博客访问: 52824
  • 博文数量: 13
  • 博客积分: 1540
  • 博客等级: 上尉
  • 技术积分: 180
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-29 10:37
文章分类

全部博文(13)

文章存档

2011年(1)

2010年(12)

我的朋友

分类: LINUX

2010-09-29 15:11:01

==============
转载请注出处  
==============

static int __init init_dazukofs_fs(void)
{
int err;

err = dazukofs_dev_init();  //字符设备文件注册
if (err)
goto error_out1;

err = init_caches();
if (err)
goto error_out2;

err = register_filesystem(&dazukofs_

fs_type);      //注册文件系统
if (err)
goto error_out3;

printk(KERN_INFO "dazukofs: loaded, version=%s\n", DAZUKOFS_VERSION);
return 0;

error_out3:
destroy_caches();
error_out2:
dazukofs_dev_destroy();
error_out1:
return err;
}
模块入口,注册字符设备及文件系统,先进入字符设备注册生成.

int dazukofs_dev_init(void)
{
int err;
dev_t devt;

err = dazukofs_init_events();
if (err)
goto error_out1;

err = alloc_chrdev_region(&devt, 0, 2 + GROUP_COUNT, DEVICE_NAME);  //动态分配10个设备
if (err)
goto error_out2;
dev_major = MAJOR(devt);                  //主
dev_minor_start = MINOR(devt);        //次

  dazukofs_class = class_create(THIS_MODULE, DEVICE_NAME);      // 在/dev 下创建设备
if (IS_ERR(dazukofs_class)) {
err = PTR_ERR(dazukofs_class);
goto error_out3;
}
err = dazukofs_ctrl_dev_init(dev_major, dev_minor_start,
    dazukofs_class);
if (err)
goto error_out4;

err = dazukofs_ign_dev_init(dev_major, dev_minor_start + 1,
   dazukofs_class);
if (err)
goto error_out5;

dev_minor_end = dazukofs_group_dev_init(dev_major,
dev_minor_start + 2,
dazukofs_class);
if (dev_minor_end < 0) {
err = dev_minor_end;
goto error_out6;
}

return 0;

error_out6:
dazukofs_ign_dev_destroy(dev_major, dev_minor_start + 1,
dazukofs_class);
error_out5:
dazukofs_ctrl_dev_destroy(dev_major, dev_minor_start, dazukofs_class);
error_out4:
class_destroy(dazukofs_class);
error_out3:
unregister_chrdev_region(MKDEV(dev_major, dev_minor_start),
2 + GROUP_COUNT);
error_out2:
dazukofs_destroy_events();
error_out1:
return err;
}
在这注册三个类型的字符设备ign,ctrl,dazudofs.*,如进入
dazukofs_ctrl_dev_init:

int dazukofs_ctrl_dev_init(int dev_major, int dev_minor,
  struct class *dazukofs_class)
{
int err = 0;
struct device *dev;

/* setup cdev for control */
cdev_init(&ctrl_cdev, &ctrl_fops);         //申请dev结构体,cdev_init函数中使用通过参数传进来的struct file_operations结构体指针对struct cdev的ops域进行初始化,所以在函数cdev_init调用之后不需要再对struct cdev的ops域进行初始化。
ctrl_cdev.owner = THIS_MODULE;
err = cdev_add(&ctrl_cdev, MKDEV(dev_major, dev_minor), 1);              //初始化后的struct cdev结构体注册到内核中,就可以访问它了.
if (err)
goto error_out1;

/* create control device */
dev = device_create(dazukofs_class, NULL, MKDEV(dev_major, dev_minor),       
   NULL, "%s.ctrl", DEVICE_NAME);
if (IS_ERR(dev)) {
err = PTR_ERR(dev);
goto error_out2;
}

return 0;

error_out2:
cdev_del(&ctrl_cdev);
error_out1:
return err;
在这里创建设备文件dazudofs.ctrl分配主,次设备号,及对该设备文件相关的操作:
static const struct file_operations ctrl_fops = {
.owner = THIS_MODULE,
.open = dazukofs_ctrl_open,
.release = dazukofs_ctrl_release,
.read = dazukofs_ctrl_read,
.write = dazukofs_ctrl_write,
};
其他二个类型的设备文件注册创建方法一样,也就不多说了.

static ssize_t dazukofs_ctrl_read(struct file *file, char __user *buffer,
 size_t length, loff_t *pos)
{
char *buf = file->private_data;
size_t buflen;
int err;

if (!file->private_data) {
err = dazukofs_get_groups(&buf);        //分配空间
if (err)
return err;
file->private_data = buf;
}
buflen = strlen(buf);

if (*pos >= buflen)
return 0;

if (length > buflen - *pos)
length = buflen - *pos;

if (copy_to_user(buffer, buf + *pos, length))
return -EFAULT;

*pos += length;

return length;
}


static ssize_t dazukofs_ctrl_write(struct file *file,
  const char __user *buffer, size_t length,
  loff_t *pos)
{
#define DAZUKOFS_MAX_WRITE_BUFFER 32
char tmp[DAZUKOFS_MAX_WRITE_BUFFER];
int match = 0;
int ret = -EINVAL;
int cp_len = length;

if (cp_len >= DAZUKOFS_MAX_WRITE_BUFFER)
cp_len = DAZUKOFS_MAX_WRITE_BUFFER - 1;

if (copy_from_user(tmp, buffer, cp_len))
return -EFAULT;

tmp[cp_len] = 0;

if (!match || (match && ret >= 0)) {
if (process_command(tmp, "del=",
   dazukofs_remove_group, 0, &ret) == 0) {
match = 1;
}
}

if (!match || (match && ret >= 0)) {
if (process_command(tmp, "add=",
   dazukofs_add_group, 0, &ret) == 0) {
match = 1;
}
}

if (!match || (match && ret >= 0)) {
if (process_command(tmp, "addtrack=",
   dazukofs_add_group, 1, &ret) == 0) {
match = 1;
}
}

if (ret >= 0) {
*pos += length;
ret = length;
}

return ret;
}
对dazukofs.ctrl读写操作都在这实现了,
read执行
,把数据拷贝到用户空间.
write执行,接受用户程序发送的字符串是否与内核字符匹配,作出相应处理(add,remove)。


再转到文件系统:
static struct file_system_type dazukofs_fs_type = {
.owner = THIS_MODULE,
.name = "dazukofs",
.get_sb = dazukofs_get_sb,
.kill_sb = kill_anon_super,
.fs_flags = 0,
};
static int dazukofs_get_sb(struct file_system_type *fs_type, int flags,
  const char *dev_name, void *data,
  struct vfsmount *mnt)
{
struct super_block *sb;
int err;

err = get_sb_nodev(fs_type, flags, data, dazukofs_fill_super, mnt);    // 真实现超级块方法
dazukofs_fill_super.
if (err)
goto out;

sb = mnt->mnt_sb;         //获取挂载点超级块

err = dazukofs_parse_mount_options(data, sb);
if (err)
goto out_abort;

err = dazukofs_read_super(sb, dev_name);   //**
if (err)
goto out_abort;

goto out;

out_abort:
dput(sb->s_root);
up_write(&sb->s_umount);
deactivate_super(sb);
out:
return err;
}
真实现超级块方法
dazukofs_fill_super在这里实现,超级块分配空间,创建,释放,文件系统状态等操作。注意
dazukofs_read_super函数,普通索引结点的操作放现去判断
static int dazukofs_fill_super(struct super_block *sb, void *data, int silent)
{
struct dazukofs_sb_info *sbi;
struct dentry *root;
static const struct qstr name = { .name = "/", .len = 1 };
struct dazukofs_dentry_info *di;

sbi =  kmem_cache_zalloc(dazukofs_sb_info_cachep, GFP_KERNEL);
if (!sbi)
return -ENOMEM;

sb->s_op = &dazukofs_sops;     //超级块操作

root = d_alloc(NULL, &name);
if (!root) {
kmem_cache_free(dazukofs_sb_info_cachep, sbi);
return -ENOMEM;
}

sb->s_root = root;        //加载根目录

sb->s_root->d_op = &dazukofs_dops;
sb->s_root->d_sb = sb;
sb->s_root->d_parent = sb->s_root;

di = kmem_cache_zalloc(dazukofs_dentry_info_cachep, GFP_KERNEL);
if (!di) {
kmem_cache_free(dazukofs_sb_info_cachep, sbi);
dput(sb->s_root);
return -ENOMEM;
}

set_dentry_private(sb->s_root, di);

set_sb_private(sb, sbi);

return 0;
}

static int dazukofs_read_super(struct super_block *sb, const char *dev_name)
{
struct nameidata nd;
struct dentry *lower_root;
struct vfsmount *lower_mnt;
int err;

memset(&nd, 0, sizeof(struct nameidata));
err = path_lookup(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &nd);
if (err)
return err;

lower_root = dget(nd.path.dentry);
lower_mnt = mntget(nd.path.mnt);

if (IS_ERR(lower_root)) {
err = PTR_ERR(lower_root);
goto out_put;
}

if (!lower_root->d_inode) {
err = -ENOENT;
goto out_put;
}

if (!S_ISDIR(lower_root->d_inode->i_mode)) {
err = -EINVAL;
goto out_put;
}
// sb = mmt->sb
set_lower_sb(sb, lower_root->d_sb);                            //设置sb
sb->s_maxbytes = lower_root->d_sb->s_maxbytes;          //填充文件大小上限
set_lower_dentry(sb->s_root, lower_root, lower_mnt);    //设置dentry

err = dazukofs_interpose(lower_root, sb->s_root, sb, 0);
if (err)
goto out_put;
goto out;

out_put:
dput(lower_root);
mntput(lower_mnt);
out:
path_put(&nd.path);
return err;
}
int dazukofs_interpose(struct dentry *lower_dentry, struct dentry *dentry,
      struct super_block *sb, int already_hashed)
{
struct inode *inode;
struct inode *lower_inode = igrab(lower_dentry->d_inode);

if (!lower_inode)
return -ESTALE;

if (lower_inode->i_sb != get_lower_sb(sb)) {
iput(lower_inode);
return -EXDEV;
}

inode = iget5_locked(sb, (unsigned long)lower_inode,
    dazukofs_inode_test, dazukofs_inode_set,
    lower_inode);

if (!inode) {
iput(lower_inode);
return -EACCES;
}

if (inode->i_state & I_NEW) {
unlock_new_inode(inode);
/*
* This is a new node so we leave the lower_node "in use"
* and do not call iput().
*/
} else {
/*
* This is not a new node so we decrement the usage count.
*/
iput(lower_inode);
}

if (S_ISLNK(lower_inode->i_mode))
inode->i_op = &dazukofs_symlink_iops;   //关联链接操作函数
else if (S_ISDIR(lower_inode->i_mode))
inode->i_op = &dazukofs_dir_iops;       //关联结点操作函数

if (S_ISDIR(lower_inode->i_mode))
inode->i_fop = &dazukofs_dir_fops;      //关联文件操作函数

if (special_file(lower_inode->i_mode)) {
init_special_inode(inode, lower_inode->i_mode,
  lower_inode->i_rdev);
}

dentry->d_op = &dazukofs_dops;           // 填充目录项操作函数

if (already_hashed)
d_add(dentry, inode);
else
d_instantiate(dentry, inode);

fsstack_copy_attr_all(inode, lower_inode);
fsstack_copy_inode_size(inode, lower_inode);
return 0;
}
例如相关文件操作,定义这些,都是通过调vfs层接口来实现的。
const struct file_operations dazukofs_dir_fops = {
.read = dazukofs_read,
.readdir = dazukofs_readdir,
.ioctl = dazukofs_ioctl,
.mmap = dazukofs_mmap,
.open = dazukofs_open,
.flush = dazukofs_flush,
.release = dazukofs_release,
.fsync = dazukofs_fsync,
.fasync = dazukofs_fasync,
.splice_read = generic_file_splice_read,
};
static ssize_t dazukofs_read(struct file *file, char *buf, size_t count,
    loff_t *ppos)
{
int err;
struct file *lower_file = get_lower_file(file);
loff_t pos_copy = *ppos;

if (!lower_file->f_op || !lower_file->f_op->read)
return -EINVAL;

err = lower_file->f_op->read(lower_file, buf, count, &pos_copy);

lower_file->f_pos = pos_copy;
*ppos = pos_copy;

if (err >= 0) {
fsstack_copy_attr_atime(file->f_dentry->d_inode,
lower_file->f_dentry->d_inode);
}

memcpy(&(file->f_ra), &(lower_file->f_ra),
      sizeof(struct file_ra_state));
return err;
}

最后在文件系统挂载后,在挂载点上建一文件,通过应用程序打印进程号及文件名,应用程序通过读取/proc文件系统下的link对应的文件,如函数:
int dazukofs_get_filename(struct dazukofs_access *acc, char *buf, size_t bufsiz)
{
char proc[48];
int ret;

memset(proc, 0, sizeof(proc));
snprintf(proc, sizeof(proc) - 1, "/proc/self/fd/%d", acc->fd);
ret = readlink(proc, buf, bufsiz - 1);
buf[bufsiz - 1] = 0;
if (ret > 0)
buf[ret] = 0;

return ret;
}

见附件。


阅读(1304) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:lseek系统调用注释

给主人留下些什么吧!~~