Chinaunix首页 | 论坛 | 博客
  • 博客访问: 677820
  • 博文数量: 118
  • 博客积分: 7172
  • 博客等级: 少将
  • 技术积分: 1799
  • 用 户 组: 普通用户
  • 注册时间: 2007-12-12 13:33
文章分类

全部博文(118)

文章存档

2012年(5)

2011年(12)

2010年(18)

2009年(36)

2008年(47)

我的朋友

分类: LINUX

2008-04-01 18:20:36

#include <linux/module.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/fs.h>
#include <linux/kernel.h>    /* printk() */
#include <asm/uaccess.h>    /* copy_*_user */

#define PROC_NAME "myproc"

static int proc_open(struct inode *inodp, struct file *filp);
static ssize_t proc_write(struct file *file, const char __user *buf, size_t size, loff_t *ppos);

static struct file_operations proc_fops = {
        .owner = THIS_MODULE,
        .open = proc_open,
        .read = seq_read,
        .write = proc_write,
        .llseek = seq_lseek,
        .release = seq_release,
};

//only for test

static ssize_t proc_write(struct file *file, const char __user *buf, size_t size, loff_t *ppos)
{
    size_t copied = 0;
    int i;
    char *kbuf;
    
    kbuf = kmalloc(size, GFP_KERNEL);
    if (!kbuf)
     goto out;    
    if (copy_from_user(kbuf, buf, size))
        goto out_cp;

    copied = size;
    *ppos += size;

//

    for(i = 0; i < size; i++)
        printk("%c", kbuf[i]);
    if (kbuf[0] == '1') {
           printk("open\n");
    } else if (kbuf[0] == '0') {
           printk("close\n");
    } else {
            printk("error\n");
    }
//

out_cp:
    kfree(kbuf);
out:    
    return copied;
}

//sfile 参数可以几乎是一直被忽略. pos 是一个整型位置值, 指示应当从哪里读. 位置的解释完全取决于实现; 在结果文件里不需要是一个字节位置. 因为 seq_file 实现典型地步进一系列感兴趣的项, position 常常被解释为指向序列中下一个项的指针. scull 驱动解释每个设备作为系列中的一项, 因此进入的 pos 简单地是一个 scull_device 数组的索引. 因此, scull 使用的 start 方法是:

void * seq_start(struct seq_file *m, loff_t *pos)
{
        loff_t *item;

        printk("seq_start %ld\n", *pos);
        item = kmalloc(sizeof(loff_t), GFP_KERNEL);
        if (!item) {
                 printk("kmalloc err\n");
                goto err;
            }

        *item = *pos;
err:
        return item;
}

void seq_stop(struct seq_file *m, void *v)
{
        kfree(v);
}

//这里, v 是从前一个对 start 或者 next 的调用返回的 iterator, pos 是文件的当前位置. next 应当递增有 pos 指向的值; 根据你的 iterator 是如何工作的, 你可能(尽管可能不会)需要递增 pos 不止是 1. 这是 scull 所做的:

void * seq_next(struct seq_file *m, void *v, loff_t *pos)
{
        loff_t *item = (loff_t *) v;
        
        *pos = ++(*item);

        return item;
}

int seq_show(struct seq_file *m, void *v)
{
        loff_t *item = (loff_t *) v;

        seq_printf(m, "%Ld\n", *item);

        return 0;
}

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

static int proc_open(struct inode *inodp, struct file *filp)
{
        printk("proc_open %\n");
        return seq_open(filp, &seq_ops);
}

static int __init proc_init(void)
{
        struct proc_dir_entry *entry;

        entry = create_proc_entry(PROC_NAME, 0, NULL);
        if (!entry)
                printk(KERN_ALERT "create failure.\n");

        entry->proc_fops = &proc_fops;

        return 0;
}

static void __exit proc_exit(void)
{
        remove_proc_entry(PROC_NAME, NULL);
}

MODULE_LICENSE("GPL");

module_init(proc_init);
module_exit(proc_exit);

阅读(1059) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~