代码之家  ›  专栏  ›  技术社区  ›  msc

使用seq_file构建Linux/proc文件驱动程序

  •  0
  • msc  · 技术社区  · 8 年前

    /proc seq_file ?

    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/proc_fs.h>
    #include <linux/seq_file.h>
    
    #define PROC_NAME "iter"
    
    MODULE_AUTHOR("MS Chaudhari");
    MODULE_LICENSE("GPL");
    
    /*  
       This function is called at the beginning of a sequence.
        ie, when:
        - the /proc file is read (first time)
        - after the function stop (end of sequence)
    */
    static void *my_seq_start(struct seq_file *s, loff_t *pos)
    {
        static unsigned long counter = 0;
    
        // beginning a new sequence
        if (*pos == 0)
        {
            return &counter;
        }
        else
        {
            *pos = 0;
            return NULL;
        }
    }
    
    /*
         This function is called after the beginning of a sequence.
         It's called untill the return is NULL (this ends the sequence).
    */
    static void *my_seq_next(struct seq_file *s, void *v, loff_t *pos)
    {
        unsigned long *tmp_v = (unsigned long *)v;
        (*tmp_v)++; 
        (*pos)++;
        return NULL;
    }
    
    /*
         This function is called for each "step" of a sequence
    */
    
    static int my_seq_show(struct seq_file *s, void *v)
    {
        loff_t *spos = (loff_t *)v;
    
        seq_printf(s, "%Ld\n", *spos);
        return 0;
    }
    
    /*
            This structure gather "function" to manage the sequnce
    */
    
    static struct seq_operation my_seq_ops = 
    {
        .start = my_seq_start,
        .next = my_seq_next,
        .stop = my_seq_stop,
        .show = my_seq_show
    };
    
    /*
         This function is called when the /proc file is open.
    */
    static int my_open(struct inode *inode, struct file *file)
    {
        return seq_open(file, &my_seq_ops);
    }
    
    /*
        This structure gather "function" that manage the /proc file
    */
    static struct file_operations fops =
    {
        .owner   = THIS_MODULE,
        .open    = my_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
        .release = seq_release
    };
    
    
    /*
        This function is called when the module is loaded
    */
    int init_module(void)
    {
        struct proc_dir_entry *entry;
    
        entry = proc_create(PROC_NAME, 0, NULL, &fops);
    
    //  entry = create_entry(PROC_NAME, 0, NULL);
        if (entry) 
        {
            entry->proc_fops = &my_file_ops;
        }
    
        return 0;
    }
    
    /*
         This function is called when the module is unloaded.
    */
    void cleanup_module(void)
    {
        remove_proc_entry(PROC_NAME, NULL);
    }
    

    make

    /home/radix/programing/DD/procSeq.c:61:15: error: variable ‘my_seq_ops’ has initializer but incomplete type
     static struct seq_operation my_seq_ops = 
                   ^
    /home/radix/programing/DD/procSeq.c:63:2: error: unknown field ‘start’ specified in initializer
      .start = my_seq_start,
      ^
    /home/radix/programing/DD/procSeq.c:63:2: warning: excess elements in struct initializer [enabled by default]
    /home/radix/programing/DD/procSeq.c:63:2: warning: (near initialization for ‘my_seq_ops’) [enabled by default]
    /home/radix/programing/DD/procSeq.c:64:2: error: unknown field ‘next’ specified in initializer
      .next = my_seq_next,
      ^
    /home/radix/programing/DD/procSeq.c:64:2: warning: excess elements in struct initializer [enabled by default]
    /home/radix/programing/DD/procSeq.c:64:2: warning: (near initialization for ‘my_seq_ops’) [enabled by default]
    /home/radix/programing/DD/procSeq.c:65:2: error: unknown field ‘stop’ specified in initializer
      .stop = my_seq_stop,
      ^
    /home/radix/programing/DD/procSeq.c:65:10: error: ‘my_seq_stop’ undeclared here (not in a function)
      .stop = my_seq_stop,
              ^
    /home/radix/programing/DD/procSeq.c:65:2: warning: excess elements in struct initializer [enabled by default]
      .stop = my_seq_stop,
      ^
    /home/radix/programing/DD/procSeq.c:65:2: warning: (near initialization for ‘my_seq_ops’) [enabled by default]
    /home/radix/programing/DD/procSeq.c:66:2: error: unknown field ‘show’ specified in initializer
      .show = my_seq_show
      ^
    /home/radix/programing/DD/procSeq.c:67:1: warning: excess elements in struct initializer [enabled by default]
     };
     ^
    /home/radix/programing/DD/procSeq.c:67:1: warning: (near initialization for ‘my_seq_ops’) [enabled by default]
    /home/radix/programing/DD/procSeq.c: In function ‘my_open’:
    /home/radix/programing/DD/procSeq.c:74:2: warning: passing argument 2 of ‘seq_open’ from incompatible pointer type [enabled by default]
      return seq_open(file, &my_seq_ops);
      ^
    In file included from /home/radix/programing/DD/procSeq.c:4:0:
    include/linux/seq_file.h:98:5: note: expected ‘const struct seq_operations *’ but argument is of type ‘struct seq_operation *’
     int seq_open(struct file *, const struct seq_operations *);
         ^
    /home/radix/programing/DD/procSeq.c: In function ‘init_module’:
    /home/radix/programing/DD/procSeq.c:102:8: error: dereferencing pointer to incomplete type
       entry->proc_fops = &my_file_ops;
            ^
    /home/radix/programing/DD/procSeq.c:102:23: error: ‘my_file_ops’ undeclared (first use in this function)
       entry->proc_fops = &my_file_ops;
                           ^
    /home/radix/programing/DD/procSeq.c:102:23: note: each undeclared identifier is reported only once for each function it appears in
    make[2]: *** [/home/radix/programing/DD/procSeq.o] Error 1
    make[1]: *** [_module_/home/radix/programing/DD] Error 2
    make[1]: Leaving directory `/usr/src/linux-headers-3.13.0-24-generic'
    make: *** [all] Error 2
    

    对不起,我的代码太长了。

    1 回复  |  直到 8 年前
        1
  •  4
  •   Serge    8 年前

    因为没有 struct seq_operation 但是 struct seq_operations