使用proc文件系统将信息从LKM写入用户空间

时间:2014-08-05 01:43:24

标签: c linux struct linux-kernel

我试图使用proc文件系统从Linux内核模块函数向用户空间写入数据。我想使用seq_file迭代实现,因此它处理页面大小和所有好东西。我有一个不断记录数据和创建结构并使用数据填充结构的函数。我想将这些结构抽取到proc文件系统,以便用户空间中的应用程序可以获取这些结构并适当地处理它们。当用户空间准备好接收数据时,它将从proc文件系统读取,这将关闭所有这些。我以为我无法将结构传递给seq_file show函数。那么我可以全局声明结构并将其打印到/proc/info函数的seq_show文件中吗?我目前正在尝试实施。

  typedef struct data_t{
    unint32_t address;
    unint8_t pid;
    unint8_t info;
  } data_t;

  data_t data = NULL;

  static void datalog(uint32_t addy, unint8_t info){
   // this function is constantly logging data
   data->address = addy;
   data->info = info;
  }

  static void *seq_start(struct seq_file *s, loff_t *pos)
  {
     // seq file start stuff
  }

  static int seq_show(struct seq_file *s, void *v)
  {
   //print the data struct to the /proc/info file
   return 0;
   }

   static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
   {
   // move the pointer along
   return v;
   }

   static void seq_stop(struct seq_file *s, void *v)
   {

   }

  static struct seq_operations seq_ops = {
 .start = seq_start,
 .next  = seq_next,
 .stop  = seq_stop,
 .show  = seq_show
  };

static int open(struct inode *inode, struct file *file)
{
 return seq_open(file, &seq_ops);
};

static struct file_operations fops = {
 .owner   = THIS_MODULE,
 .open    = open,
 .read    = seq_read,
 .llseek  = seq_lseek,
 .release = seq_release
};

 static int init(void)
 {
 struct proc_dir_entry *entry = NULL;
 entry = proc_create("info", 0777, NULL, &fops);
 data = (data_t *) kmalloc(sizeof(data_t), GFP_KERNEL);
 return 0;
 }

因此datalog函数已经处于一个常量循环中。我想将所有这些结构抽取到/proc/info文件中,以便可以在用户空间中对其进行适当处理。这将是快速的火灾数据,所以它不会感觉copy_to_user是要走的路。正如你所看到的,我不确定我做了什么,所以任何方向或帮助都非常感谢!谢谢!

1 个答案:

答案 0 :(得分:0)

假设你正在维护一个struct data的数组,而count就是这样的结构。以下函数应该可以帮助您从用户空间中读取结构。下面的代码假设您在阅读时不会修改日志缓冲区或数组(这是一个简单的示例)。您可以修改以下内容以满足您的需求。确保同步数据结构(例如日志缓冲区)以确保您阅读的内容是什么。

是的!你可以使用全局声明结构并在seq_show中使用它。

static void *seq_start(struct seq_file *s, loff_t *pos)
{
    if (*pos > count)
        return NULL;
    return pos;
}

static int seq_show(struct seq_file *s, void *v)
{
    loff_t *pos = (loff_t *)v;

    if (*pos == 0) {
        seq_printk(s, "Address\t\t\tPID\tInfo\n");
    }
    seq_printk(s, "0x%p\t%u\t%u\n", drv_data[*pos].address, drv_data[*pos].pid,
                     drv_data[*pos].info);
    return 0;
}

static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
{
    (*pos)++;
    if (*pos >= count)
        return NULL;
    return pos;
}