2018年2月13日 星期二

Linux kernel - 建立/sys文件系统訪問kernel - seq_open

#include <linux/module.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>

MODULE_LICENSE("Dual BSD/GPL");

#define PROCNAME "sample"

static char *data_message[] = {
 "Fedora",
 "Red Hat",
 "Debian",
 "Ubuntu",
 0
};

static void *as_start(struct seq_file *m, loff_t *pos)
{
 loff_t n = *pos;
 char **ptr;
 int i;

 seq_printf(m, "%lld (%s)\n", n, __func__);

 if (n == 0)
  seq_printf(m, "=== seq_file header ===\n");

 ptr = data_message;

 for (i = 0; ptr[i]; i++) {
  n--;
  if (n < 0) {
   return (void *) (i + 1);
  }
 }
 
 return 0;
}

static void *as_next(struct seq_file *m, void *p, loff_t *pos)
{
 int n = (int) p;
 char **ptr;

 seq_printf(m, "%u (%s)\n", n, __func__);

 (*pos)++;

 ptr = data_message;

 if (ptr[n])
  return (void *) (n + 1);
 
 return 0;
}

static void as_stop(struct seq_file *m, void *p)
{
 int n = (int) p;

 seq_printf(m, "%u (%s)\n", n, __func__);
}

static int as_show(struct seq_file *m, void *p)
{
 int n = (int) p - 1;

 seq_printf(m, "%u (%s)\n", (int) p, __func__);
 seq_printf(m, "[%d] %s\n", n, data_message[n]);

 return 0;
}

/* seq_file handler */
static struct seq_operations sample_seq_op = {
 .start  = as_start,
 .next  = as_next,
 .stop  = as_stop,
 .show  = as_show,
};

static int sample_proc_open(struct inode *inode, struct file *file)
{
 return seq_open(file, &sample_seq_op);
}

/* procfs handler */
static struct file_operations sample_proc_fops = {
 .open  = sample_proc_open,
 .read  = seq_read,
 .llseek  = seq_lseek,
 .release = seq_release,
};

static int sample_init(void)
{
#if 1
 struct proc_dir_entry *entry;
 
 entry = create_proc_entry(PROCNAME, S_IRUGO | S_IWUGO, NULL);

 if (entry)
  entry->proc_fops = &sample_proc_fops;
#else
 proc_create(PROCNAME, 0, NULL, &sample_proc_fops);
#endif

 printk(KERN_INFO "driver loaded\n");

 return 0;
}

static void sample_exit(void)
{
 remove_proc_entry(PROCNAME, NULL);

 printk(KERN_INFO "driver unloaded\n");
}
module_init(sample_init);
module_exit(sample_exit);

沒有留言:

張貼留言