proc文件系统和seq_file

来源:互联网 发布:java大学简明教程实例 编辑:程序博客网 时间:2024/05/03 20:52

首先需要说明的是本文是博文《Linux内核调试技术 - 基础篇》的一部分,为了清晰先将篇幅比较大的单独成文。


procfs 是 Linux内核中较老的一种虚拟文件系统,是一种用户态与内核态的数据交换方式。正如她的名字所示最初主要是用来显示内核进程的相关信息,后来各个子系统(比如net,fs,scsi,dma等等)的信息也加了进来,导致proc成了一个大杂烩。

sysfs 是Linux 内核中较新的一种虚拟文件系统,利用Linux设备模型将内核中的device和driver的信息导出到用户空间,现在的设备和驱动信息推荐使用sysfs。

 

在调试的时候,为了方便需要在内核启动完毕后启动内核测试程序,并能够打印测试结果,proc提供了简单方便的调试途径。这里简单说下proc的常用API,然后给出我调试时使用的一些代码。


1. proc API


头文件:

#include <linux/proc_fs.h>

在proc目录下创建目录:

struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent);name是目录名称,parent是父目录,如在proc目录下,则设为NULL

在目录下创建一个entry:

struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,                                         struct proc_dir_entry *parent);name指定entry的名称,mode指定entry的访问权限,parent指定entry所在的目录struct proc_dir_entry *proc_create(const char *name, mode_t mode,        struct proc_dir_entry *parent, const struct file_operations *proc_fops);name/mode/parent也上面相同。proc_fops指定操作该entry使用的读写函数,这个函数主要是可以提供一个seq_file操作结构来读取entry的信息。为什么要使用seq_file来完成读取操作呢?就是为了方便读取操作


删除上面创建的目录或者entry:

void remove_proc_entry(const char *name, struct proc_dir_entry *parent);name是目录名称,parent是创建时指定的父目录

2. seq_file


The seq_file API: Seq_file was designed tofacilitate the handling of read requests.


头文件:

#include <linux/seq_file.h>


seq_file: http://lwn.net/Articles/22355/


具体使用看下面代码吧。


3. 调试代码


在proc目录下创建xxx_test目录,在xxx_test目录下创建xxx_cmd和xxx_result两个entry。

xxx_cmd用来接收用户输入的命令;xxx_result用来打印测试结果。可以添加相应的测试函数并打印测试信息。


~# ls /proc/xxx_test/
xxx_cmd     xxx_result
~# echo 1 > /proc/xxx_test/xxx_cmd
Start test...
~# echo 2 > /proc/xxx_test/xxx_cmd
Stop stop...
~# cat /proc/xxx_test/xxx_result
Vcore     :       1 mV
Icore     :       2 mA
Core Pwr  :       2  mW

Vplat     :       4 mV
Iplat     :       5 mA
Plat Pwr  :       6  mW


#include <linux/kernel.h>#include <linux/err.h>#include <linux/proc_fs.h>#include <linux/seq_file.h>#define XXX_CMD_START   1#define XXX_CMD_STOP    2/* Get command */static int xxx_proc_write_cmd(struct file *file, const char __user *buffer,                               unsigned long count, void *data){        u8 local_buf[count + 1];        int err;        unsigned long cmd;        if (copy_from_user(local_buf, buffer, count))                return -EFAULT;        local_buf[count] = '\0';        err = strict_strtoul(local_buf, 10, &cmd);        if (err)                return err;        switch (cmd) {        case XXX_CMD_START:                pr_info("Start test...\n");                break;        case XXX_CMD_STOP:                pr_info("Stop test...\n");                break;        default:                return -EIO;        }        return count;}/* Show result */static int xxx_proc_show_result(struct seq_file *m, void *v){        seq_printf(m, "Vcore     :    %4d  mV\n", 1);        seq_printf(m, "Icore     :    %4d  mA\n", 2);        seq_printf(m, "Core Pwr  :    %4d  mW\n", 2);        seq_putc(m, '\n');        seq_printf(m, "Vplat     :    %4d  mV\n", 4);        seq_printf(m, "Iplat     :    %4d  mA\n", 5);        seq_printf(m, "Plat Pwr  :    %4d  mW\n", 6);        seq_putc(m, '\n');        return 0;}static int xxx_proc_result_open(struct inode *inode, struct file *file){        return single_open(file, xxx_proc_show_result, NULL);}static const struct file_operations xxx_proc_result_fops = {        .open           = xxx_proc_result_open,        .read           = seq_read,        .llseek         = seq_lseek,        .release        = single_release,};static int __init xxx_test_init(void){        struct proc_dir_entry *xxx_proc_root;        struct proc_dir_entry *xxx_proc_cmd;        /* Create the /proc entry */        xxx_proc_root = proc_mkdir("xxx_test", NULL);        if (!xxx_proc_root)                return -ENOMEM;        xxx_proc_cmd = create_proc_entry("xxx_cmd", S_IRUGO | S_IWUSR,                                                xxx_proc_root);        xxx_proc_cmd->write_proc = xxx_proc_write_cmd;        proc_create("xxx_result", 0, xxx_proc_root, &xxx_proc_result_fops);        return ret;}static void __exit xxx_test_exit(void){        remove_proc_entry("xxx_cmd", xxx_proc_root);        remove_proc_entry("xxx_test", NULL);}module_init(xxx_test_init);module_exit(xxx_test_exit);

原创粉丝点击