您的位置:首页 > 其它

浅析debugfs文件系统调试阶段gpio使用范例

2011-08-15 15:01 337 查看
转自:http://blog.chinaunix.net/space.php?uid=20564848&do=blog&id=73448

=========================================================================================

我们对debugfs文件系统的应用之1是:drivers/gpio/gpiolib.c它创建了一个名为"gpio"的文件,然后我们可以使用

'-'表示output

'+'表示input

echo -170=0>/d/gpio

echo -96 =0>/d/gpio //必须让'='索引为4,所以需要补齐,这是驱动的一个bug

以上2个操作是将cpu的170脚和96脚置低,对于调试很方便,当然debugfs要想使用必须在make menuconfig时打开

Kernel hacking=> -*- Debug
Filesystem保存之后,在

vim .config可以看到CONFIG_DEBUG_FS=y

static int __init gpiolib_debugfs_init(void)

{

/* /sys/kernel/debug/gpio */

(void) debugfs_create_file("gpio", S_IFREG | S_IRUGO | S_IWUSR | S_IWGRP,

NULL, NULL, &gpiolib_operations);

return 0;

}

subsys_initcall(gpiolib_debugfs_init);

=========================================================================================

在我们的系统system/rootdir/init.rc启动脚本中存在如下2行,进而将debugfs文件系统挂载到/d目录下[luther.gliethttp],

...

mkdir /d

...

mount debugfs debugfs /d

这和在init进程中,通过语句mount sys,pts和dev效果一样.

mkdir("/dev", 0755);

mkdir("/dev/pts", 0755);

mkdir("/sys", 0755);

mount("tmpfs", "/dev", "tmpfs", 0, NULL);

mount("devpts", "/dev/pts", "devpts", 0, NULL);

mount("sysfs", "/sys", "sysfs", 0, NULL);

=========================================================================================

=>debugfs_create_file

=>simple_pin_fs(&debug_fs_type, &debugfs_mount, &debugfs_mount_count);

static struct vfsmount *debugfs_mount;

static int debugfs_mount_count;

static struct file_system_type debug_fs_type = {

.owner = THIS_MODULE,

.name = "debugfs",

.get_sb = debug_get_sb,

.kill_sb = kill_litter_super,

};

=========================================================================================

struct dentry *debugfs_create_file(const char *name, mode_t
mode,

struct dentry *parent, void *data,

const struct file_operations *fops)

{

struct dentry *dentry = NULL;

int error;

pr_debug("debugfs: creating file '%s'\n",name);

error = simple_pin_fs(&debug_fs_type, &debugfs_mount,

&debugfs_mount_count);

if (error)

goto exit;

error = debugfs_create_by_name(name, mode, parent, &dentry);//创建名字为name的文件[目录,设备节点或者目录,符号链接等]

if (error) {

dentry = NULL;

simple_release_fs(&debugfs_mount, &debugfs_mount_count);

goto exit;

}

if (dentry->d_inode) {

if (data)

dentry->d_inode->i_private = data;//传递的open之后file结构题的private参数

if (fops)

dentry->d_inode->i_fop = fops;//如果用户定义了对新创建的inode文件的函数操作集,那么将自定义函数集作为用户程序操作该文件时,open,read,write等操作函数集,这是debugfs文件系统提供的最有用接口,让我们完全控制inode文件的操作函数集[luther.gliethttp].

}

exit:

return dentry;

}

//文件系统安装和引用计数操作

//如果debugfs文件系统超级块没有创建,那么创建之

=>

int simple_pin_fs(struct file_system_type *type, struct vfsmount **mount, int *count)

{

struct vfsmount *mnt = NULL;

spin_lock(&pin_fs_lock);

if (unlikely(!*mount)) { //*mount指向的存储指针的内存为0,第一次运行会执行,此时debugfs_mount存储单元中数据为0,没有指向任何数据

spin_unlock(&pin_fs_lock);

mnt = vfs_kern_mount(type, 0, type->name, NULL);

if (IS_ERR(mnt))

return PTR_ERR(mnt);

spin_lock(&pin_fs_lock);

if (!*mount)

*mount = mnt;//将mnt数据指针存储到*mount指向的指针存储空间&debugfs_mount中[luther.gliethttp].

}

mntget(*mount);

++*count;

spin_unlock(&pin_fs_lock);

mntput(mnt);

return 0;

}

=>simple_pin_fs

=>vfs_kern_mount

struct vfsmount *

vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)

{

struct vfsmount *mnt;

char *secdata = NULL;

int error;

if (!type)

return ERR_PTR(-ENODEV);

error = -ENOMEM;

mnt = alloc_vfsmnt(name); //从slab上摘下一个空内存对象

if (!mnt)

goto out;

if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) {

secdata = alloc_secdata();

if (!secdata)

goto out_mnt;

error = security_sb_copy_data(data, secdata);

if (error)

goto out_free_secdata;

}

error = type->get_sb(type, flags, name, data, mnt);//调用debug_fs_type获取超级块sb的方法

if (error < 0)

goto out_free_secdata;

BUG_ON(!mnt->mnt_sb);

error = security_sb_kern_mount(mnt->mnt_sb, secdata);

if (error)

goto out_sb;

mnt->mnt_mountpoint = mnt->mnt_root;//mount的目录项

mnt->mnt_parent = mnt;//因为是root根,所以parent为自己

up_write(&mnt->mnt_sb->s_umount);

free_secdata(secdata);

return mnt;//ok,mount结构体成功创建

out_sb:

dput(mnt->mnt_root);

up_write(&mnt->mnt_sb->s_umount);

deactivate_super(mnt->mnt_sb);

out_free_secdata:

free_secdata(secdata);

out_mnt:

free_vfsmnt(mnt);

out:

return ERR_PTR(error);

}

static int debug_get_sb(struct file_system_type *fs_type,

int flags, const char *dev_name,

void *data, struct vfsmount *mnt)

{

return get_sb_single(fs_type, flags, data, debug_fill_super, mnt);//填充超级块sb的方法debug_fill_super

}

int get_sb_single(struct file_system_type *fs_type,

int flags, void *data,

int (*fill_super)(struct super_block *, void *, int),

struct vfsmount *mnt)

{

struct super_block *s;

int error;

s = sget(fs_type, compare_single, set_anon_super, NULL);

//sget=>alloc_super=>kzalloc(sizeof(struct super_block),GFP_USER);从malloc_sizes[]数组中申请一个大小适合的slab空闲对象空间

if (IS_ERR(s))

return PTR_ERR(s);

if (!s->s_root) {//ok,当前该超级块sb还没有root根目录结构体

s->s_flags = flags;

error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);//填充超级块sb的root根目录结构体

if (error) {

up_write(&s->s_umount);

deactivate_super(s);

return error;

}

s->s_flags |= MS_ACTIVE;

}

do_remount_sb(s, flags, data, 0);//执行sb->s_op->remount_fs,这里没有定义该方法

return simple_set_mnt(mnt, s);//该mount结构体管理s超级块,mnt->mnt_root
= dget(sb->s_root);

}

static int debug_fill_super(struct super_block *sb, void *data, int silent)

{

static struct tree_descr debug_files[] = {{""}};

return simple_fill_super(sb, DEBUGFS_MAGIC, debug_files);//填充超级块sb的root根目录结构体信息

//simple_fill_super

//=>inode = new_inode(s);申请节点

//=>root = d_alloc_root(inode);申请目录项dentry

//s->s_root = root;将root赋值给超级块sb,作为超级块的目录项,然后函数return 0;

}

int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb)

{

mnt->mnt_sb = sb;//超级块

mnt->mnt_root = dget(sb->s_root);//该超级块对应的节点目录项,

//[注意:一个文件预想在系统中存在那么必须具备1.inode节点;2.denty目录项,对于二者的关系,可以参照以前的文章[luther.gliethttp]]

return 0;

}

=========================================================================================
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: