author: jonathan
本文档的CopyRight归jonathan所有,可自由转载,转载时请保持文档的完整性。
/*---------------------------------------------------------------------------------------------------------------------*/
什么是不常见的文件系统?其实我也说不清,如ramfs->rootfs -> tmpfs ->initramfs->romfs->...等等,这些算不算呢?哎,算了,看到那里就算那里了。
1 Debugfs简介
Debugfs文件系统目的是为开发人员提供更多内核数据,方便调试内容. 我们知道/proc文件系统关注的是进程信息,/sysfs关注是one-value-per-file策略集,而Debugfs文件系统没有如此多限制,可是任何内核要输出的信息。
2 Debugfs使用
2.1 安装文件系统
Debugfs没有物理设备,其挂载方式:
mount -t debugfs none /sys/kernel/debug
2.2 编程使用
2.2.1 要使用Debugfs的模块需要包含<linux/debugfs.h>
2.2.2 具体步骤
a 创建目录。所有该模块输出的信息都在该目录下面。
struct dentry *debugfs_create_dir(const char *name, struct dentry *parent);
b 创建文件。在上面创建的目录下面创建文件。
struct dentry *debugfs_create_file(const char *name, mode_t mode, struct dentry *parent, void *data,
const struct file_operations *fops);
通过fops操作文件的读写等请求,文件一般用来传递字符创等信息。
c 对于数字情况下,就没有必须通过文件来传递信息了。Debugfs提供了针对数字的接口:
struct dentry *debugfs_create_u8(const char *name, mode_t mode, struct dentry *parent, u8 *value);
struct dentry *debugfs_create_u16(const char *name, mode_t mode, struct dentry *parent, u16 *value);
struct dentry *debugfs_create_u32(const char *name, mode_t mode, struct dentry *parent, u32 *value);
struct dentry *debugfs_create_u64(const char *name, mode_t mode, struct dentry *parent, u64 *value);
struct dentry *debugfs_create_bool(const char *name, mode_t mode, struct dentry *parent, u32 *value);
struct dentry *debugfs_create_blob(const char *name, mode_t mode, struct dentry *parent,
struct debugfs_blob_wrapper *blob);
d 模块卸载,需要主动删除目录下的文件。
void debugfs_remove_recursive(struct dentry *dentry);
3 Debugfs内核代码分析
3.1 初始化和释放资源
static int __init debugfs_init(void)
{
int retval;
/* 创建kobject */
debug_kobj = kobject_create_and_add("debug", kernel_kobj);
if (!debug_kobj)
return -EINVAL;
/* 注册文件系统 */
retval = register_filesystem(&debug_fs_type);
if (retval)
kobject_put(debug_kobj);
else
debugfs_registered = true;
return retval;
}
static void __exit debugfs_exit(void)
{
debugfs_registered = false;
simple_release_fs(&debugfs_mount, &debugfs_mount_count);
unregister_filesystem(&debug_fs_type);
kobject_put(debug_kobj);
}
3.2 关键函数
debugfs_create_file函数是关键函数,其他接口基本都是该接口的wrapper。
3.2.1 变参数宏的定义
#define pr_debug(fmt, ...) do { /
dynamic_pr_debug(fmt, ##__VA_ARGS__); /
} while (0)
dynamic_pr_debug 也是变参数的.
3.2.2 debugfs_create_file
/* 挂载点 */
static struct vfsmount *debugfs_mount;
/* 引用计数 */
static int debugfs_mount_count;
static bool debugfs_registered;
/* 多条目数据结构 */
struct debugfs_blob_wrapper {
void *data;
unsigned long size;
};
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);
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;
if (fops)
dentry->d_inode->i_fop = fops;
}
exit:
return dentry;
}
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)) {
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;
}
/* 增加挂载点引用计数 */
mntget(*mount);
++*count;
spin_unlock(&pin_fs_lock);
mntput(mnt);
return 0;
}
static int debugfs_create_by_name(const char *name, mode_t mode,
struct dentry *parent,
struct dentry **dentry)
{
int error = 0;
/* If the parent is not specified, we create it in the root.
* We need the root dentry to do this, which is in the super
* block. A pointer to that is in the struct vfsmount that we
* have around.
*/
/* 英文说和很明白了 */
if (!parent) {
if (debugfs_mount && debugfs_mount->mnt_sb) {
parent = debugfs_mount->mnt_sb->s_root;
}
}
if (!parent) {
pr_debug("debugfs: Ah! can not find a parent!/n");
return -EFAULT;
}
*dentry = NULL;
mutex_lock(&parent->d_inode->i_mutex);
/* namei.c中根据名称查找目录, 在以前的文件系统分析中有介绍,这里不再累赘.
* 主要过程: 根据name,计算hash; 在name_hash_table查找dentry;如果没有找到,则d_alloc;遍历到结尾得到该文件的dentry
*/
*dentry = lookup_one_len(name, parent, strlen(name));
if (!IS_ERR(*dentry)) {
/* 以下三函数首先对mode设置合时的模式,然后都最终调用debugfs_get_inode,建立dentry与inode的联系*/
switch (mode & S_IFMT) {
case S_IFDIR:
error =debugfs_mkdir(parent->d_inode, *dentry, mode);
break;
case S_IFLNK:
error =debugfs_link(parent->d_inode, *dentry, mode);
break;
default:
error =debugfs_create(parent->d_inode, *dentry, mode);
break;
}
dput(*dentry);
} else
error = PTR_ERR(*dentry);
mutex_unlock(&parent->d_inode->i_mutex);
return error;
}
/* 根据超级块分配新的inode */
static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t dev)
{
struct inode *inode = new_inode(sb);
if (inode) {
inode->i_mode = mode;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
switch (mode & S_IFMT) {
default:
init_special_inode(inode, mode, dev);
break;
case S_IFREG:
inode->i_fop = &debugfs_file_operations;
break;
case S_IFLNK:
inode->i_op = &debugfs_link_operations;
break;
case S_IFDIR:
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
/* directory inodes start off with i_nlink == 2
* (for "." entry) */
inc_nlink(inode);
break;
}
}
return inode;
}
const struct file_operations debugfs_file_operations = {
.read = default_read_file,
.write = default_write_file,
.open = default_open,
};
const struct file_operations simple_dir_operations = {
.open = dcache_dir_open,
.release = dcache_dir_close,
.llseek = dcache_dir_lseek,
.read = generic_read_dir,
.readdir = dcache_readdir,
.fsync = simple_sync_file,
};
const struct inode_operations simple_dir_inode_operations = {
.lookup = simple_lookup,
};
3.3 其他函数
struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
{
return debugfs_create_file(name,
S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
parent, NULL,NULL);
}
struct dentry *debugfs_create_bool(const char *name, mode_t mode,
struct dentry *parent, u32 *value)
{
return debugfs_create_file(name, mode, parent, value, &fops_bool);
}
由以上可以看出,其他的输出信息都是debugfs_create_file的包装,这里主要是debugfs_create_file函数最后一个参数struct file_operations不同而已。
这里以bool类型为例:
static ssize_t read_file_bool(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
char buf[3];
/* 存储内部保存的数据 */
u32 *val = file->private_data;
if (*val)
buf[0] = 'Y';
else
buf[0] = 'N';
buf[1] = '/n';
buf[2] = 0x00;
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
}
static ssize_t write_file_bool(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
{
char buf[32];
int buf_size;
/* 存储内部保存的数据 */
u32 *val = file->private_data;
buf_size = min(count, (sizeof(buf)-1));
if (copy_from_user(buf, user_buf, buf_size))
return -EFAULT;
switch (buf[0]) {
case 'y':
case 'Y':
case '1':
*val = 1;
break;
case 'n':
case 'N':
case '0':
*val = 0;
break;
}
return count;
}
static const struct file_operationsfops_bool= {
.read =read_file_bool,
.write =write_file_bool,
.open = default_open,
相关推荐
在生成配置文件时,需要选择合适的配置选项,例如 General Setup->Initial RAM filesystem and RAM disk(initramfs/initrd) support、Kernel hacking->Kernel debugging、Kernel hacking->Compile the kernel with ...
* Kernel->user space relay support (formerly relayfs):在某些文件系统上(比如 debugfs)提供从内核空间向用户空间传递大量数据的接口。 * Initramfs source file(s):initrd 已经被 initramfs 取代,如果你不...
这些技术包括使用Linux内核提供的设施,如sysfs、debugfs、usbmon、动态调试接口和tracepoints。sysfs是Linux内核中的一个文件系统,通过它可以访问和控制内核中的各种设备和驱动程序。usbmon是Linux系统中用于监控...
这些选项包括指定目标架构(`--host=arm-linux`),使用的编译器(`CC=arm-hismall-linux-gcc`),以及其他各种禁用的功能,例如调试信息(`--disable-debugfs`)、图像生成(`--disable-imager`)等。 2. **构建静态版本的 ...
为某些文件系统(如debugfs)提供从内核空间到用户空间的数据传递接口,适用于调试和其他高级用途。 - **initramfs源文件 (Initramfs source file(s)):** initramfs是早期初始化过程的一部分,用于加载必要的模块...
- **Kernel -> userspace relays support (formerly relayfs)**: 提供内核到用户空间的中继支持,类似于debugfs,为内核调试提供了便利。 - **Initramfs source file(s)**: 指定initramfs源文件。随着initrd被...
提供从内核空间向用户空间传输大量数据的接口,主要用于debugfs等特殊文件系统。 - **Initramfs source file(s)** 替代initrd,用于加载初始RAM文件系统。对于不了解其作用的用户,建议维持默认设置。 - **...
此选项提供了从内核空间向用户空间传递大量数据的接口,例如debugfs。 **19. initramfs源文件 (Initramfs source file(s))** initramfs(初始RAM文件系统)是一种特殊的文件系统,用于存放启动过程中所需的文件和...
- **Kernel->user space relay support**:为内核到用户空间的数据传递提供接口,如debugfs。 8. **启动相关**: - **Initramfs source file(s)**:initramfs是现代Linux系统中替代initrd的启动镜像,用于加载...
- **调试选项**: 使用 `debugfs` 文件系统中的工具进行内存管理调试。 **设备树内存信息** - **设备树**: 是一种用于描述硬件配置的文件格式,Linux内核通过设备树来获取系统硬件信息。 - **内存信息**: 设备树中...
如果以上步骤无法解决问题,可能需要更深入的诊断,如检查硬盘的SMART(Self-Monitoring, Analysis, and Reporting Technology)状态,或者使用`debugfs`等工具进行低级检查和修复。 总之,正确挂载新硬盘到Ubuntu ...
这项配置为某些文件系统(如debugfs)提供了一个从内核空间向用户空间传输大量数据的接口,对于开发和调试非常有用。 ##### 3. **initramfs源文件(Initramfs source file(s))** initramfs已经取代了传统的initrd。...
此外,内核提供了一些调试工具,如`debugfs`和`ftrace`,可以帮助开发者深入分析驱动程序的性能和错误。 总的来说,"pmi.rar_V2"提供的内容涉及到了Linux系统下的硬件驱动开发,包括PMI驱动的源代码实现和头文件...
系统中新增加的调试文件系统(Debugfs)、追踪文件系统(Tracefs)、系统文件系统(Sysfs)、临时文件系统(tmpfs)以及根文件系统(Rootfs)都包含了相应的SELinux策略。 在Android 8.0中还增加了对新的系统映像...
此功能类似于debugfs,提供了从内核向用户空间发送调试信息的能力。 ##### 8. **Debugging and Monitoring** - **Load all symbols for debugging/kksymoops**:加载所有符号用于调试。这使得在发生崩溃时更容易...
Kernel->user space relay support 选项可以在某些文件系统上(例如 debugfs)提供从内核空间向用户空间传递大量数据的接口。 Initramfs source file(s) 选项 initrd 已经被 initramfs 取代,如果您不明白这是什么...
对于调试文件系统(如debugfs)来说尤其重要。 #### 十一、初始化RAM磁盘 (Initramfs Source File(s)) **11.1 初始化RAM磁盘源文件 (Initramfs source file(s))** initramfs(初始化RAM磁盘)是一个临时的根文件...
rootroot@rootroot-E400:~/wyb/ap6212a0_a33_sc3817r/lichee/linux-3.4$ make ARCH=arm menuconfig [*] Networking support ---> <*> Bluetooth subsystem support ---> Bluetooth device drivers ---> < > ...
本文件中的 nand_init()函数,本例使用后者。fs2410.c代码如下: #if defined(CONFIG_CMD_NAND) typedef enum { NFCE_LOW, NFCE_HIGH } NFCE_STATE; static inline void NF_Conf(u16 conf) { S3C2410_...
(以后重新解压缩SDK的时候,直接导入这个.config文件即可!) 2、(这个不修改:) Q:\a33\ap6212a0_a33_sc3817r\android\device\softwinner\astar-y3\overlay\frameworks\base\core\res\res\values\config.xml...