Linux kernel 始终在count bytes设置为零的情况下调用/proc/entry的write方法

Linux kernel 始终在count bytes设置为零的情况下调用/proc/entry的write方法,linux-kernel,kernel-module,Linux Kernel,Kernel Module,我试图理解procfs的seq文件接口。我创建了一个小型内核模块,用于读取/写入proc条目。我写的模块是: #define PROC_DIR_NAME "driver/kernel_test_dir2" #define KERNEL_DATA "This is kernel test" static struct proc_dir_entry *proc_entry_file = 0; static struct proc_dir_entry *proc_dir = 0; #define

我试图理解procfs的seq文件接口。我创建了一个小型内核模块,用于读取/写入proc条目。我写的模块是:

#define PROC_DIR_NAME "driver/kernel_test_dir2"
#define KERNEL_DATA "This is kernel test"

static struct proc_dir_entry *proc_entry_file = 0;
static struct proc_dir_entry *proc_dir = 0;

#define PROC_ENTRY_BUFFER_SIZE 64

struct proc_entry
{
    ssize_t buffer_length;
    char buffer[PROC_ENTRY_BUFFER_SIZE];
};

static int proc_entry_seq_show(struct seq_file *s, void *v)
{
    printk(KERN_INFO "kernel_test:proc_entry_seq_show\n");
    struct proc_entry* kmem = s->private;

    if(kmem)
    {
        printk(KERN_INFO "kernel_test:proc_entry_seq_show:s->private=%x\n",s->private);
        seq_printf(s, "%s\n",&(kmem->buffer[0]));
    }
    return 0;
}

static int proc_entry_open(struct inode *inode, struct file *file)
{
    struct proc_entry* kmem = kmalloc(sizeof(struct proc_entry),GFP_KERNEL);
    return single_open(file,&proc_entry_seq_show,(void*)kmem);
};

static int proc_entry_close(struct inode *inode, struct file *file)
{
    struct seq_file *s =  file->private_data;
    struct proc_entry* kmem = (struct proc_entry*)(s->private);
    kfree(kmem);
    return single_release(inode,file);
};

static ssize_t proc_entry_write(struct file *file, const char *buf,
size_t count, loff_t *ppos)
{
    ssize_t len=0;
    loff_t pos;
    struct seq_file* seqfile = (struct seq_file*)(file->private_data);

    printk(KERN_INFO "kernel_test:proc_entry_write\n");
    printk(KERN_INFO "kernel_test:proc_entry_write:offset = %d, count=%d\n",*ppos,count);

    if(seqfile)
    {
        printk(KERN_INFO "kernel_test:proc_entry_write:seqfile\n");
        struct proc_entry* kmem = (struct proc_entry*)(seqfile->private);
        if(kmem)
        {
            printk(KERN_INFO "kernel_test:proc_entry_write:kmem\n");
            pos = *ppos;
            if(pos<0)
                return -EINVAL;
            if(count > PROC_ENTRY_BUFFER_SIZE)
                count = PROC_ENTRY_BUFFER_SIZE;

            if(copy_from_user(&(kmem->buffer[0]), buf, count))
                return -EFAULT;
            (*ppos) = pos + count;

            kmem->buffer_length = count;
            return count;
        }
        printk(KERN_INFO "kernel_test:proc_entry_write:kmem does not exist!\n");
    }
    printk(KERN_INFO "kernel_test:proc_entry_write:seqfile does not exist!\n");
    return -EFAULT;
}

static struct file_operations fops_proc_entry = {
    .open       = proc_entry_open,
    .read       = seq_read,
    .release    = proc_entry_close,
    .write      = proc_entry_write,
};

static int __init init_test_kernel(void) {
    int rv;
    proc_dir = proc_mkdir(PROC_DIR_NAME, NULL);
    if(proc_dir == NULL) {
        rv = -ENOMEM;
    }
    proc_entry_file = proc_create ("kernel_test_file", S_IRUSR | S_IWUSR, proc_dir,&fops_proc_entry);
    if(!proc_entry_file) {
        rv = -ENOMEM;
    }

    printk(KERN_INFO "kernel_test: Kernel Test module started\n");
    return 0;
}


// Cleanup module
static void __exit cleanup_test_kernel(void) {
    remove_proc_entry("kernel_test_file", proc_dir);
    remove_proc_entry(PROC_DIR_NAME,NULL);
    printk(KERN_INFO "kernel_test: Kernel Test module stopped\n");
}

module_init(init_test_kernel);
module_exit(cleanup_test_kernel);

似乎使用“count”的正确值正确调用了write函数。我没有使用单printk语句来编写多个变量值,而是对每个要打印的变量使用单printk,它可以正确地打印值。但是printf说明符
%d
指的是公共
int
,在许多平台上是32位宽度。因此,
printk
输出的不是计数变量作为第二个字段,而是其第一个参数的一部分,
*ppos
。使用
-Wall
编译模块会发现这些问题。谢谢Tsyvarev。我现在明白了。非常感谢您的输入。看来write函数调用正确,且“count”的值正确。我没有使用单printk语句来编写多个变量值,而是对每个要打印的变量使用单printk,它可以正确地打印值。但是printf说明符
%d
指的是公共
int
,在许多平台上是32位宽度。因此,
printk
输出的不是计数变量作为第二个字段,而是其第一个参数的一部分,
*ppos
。使用
-Wall
编译模块会发现这些问题。谢谢Tsyvarev。我现在明白了。我感谢你的意见。
#define BUFFER_DATA "This is test kernel data by me"
#define MAX_BUFFER_SIZE 64

static char write_buffer[MAX_BUFFER_SIZE];
static char read_buffer[MAX_BUFFER_SIZE];

int main()
{
    int fd;
    int count=0;

    fd = open("/proc/driver/kernel_test_dir2/kernel_test_file",O_RDWR);
    if(fd<0)
    {
        std::cout <<"Could not open file /proc/driver/kernel_test_dir2/kernel_test_file !"<<
        strerror(errno)<<std::endl;
        return -1;
    }

    sprintf(write_buffer,"%s",BUFFER_DATA);
    std::cout << "Write Buffer to be written is - "<<write_buffer<<std::endl;
    count = write(fd,write_buffer,strlen(write_buffer));
    std::cout << "The bytes requested to be written are - "<<strlen(write_buffer) <<std::endl;
    if(count<0)
    {
        std::cout<<"write error : " << strerror(errno)<<std::endl;
        return -1;
    }
    else if(count!=strlen(write_buffer))
    {
        std::cout<<"Wrote only "<<count<<" bytes, but was asked to write "<<strlen(write_buffer)<<" bytes"<<std::endl;
        return -1;
    }

    count = read(fd,read_buffer,MAX_BUFFER_SIZE);
    if(count < 0)
    {
        std::cout<<"read error : " << strerror(errno)<<std::endl;
        return -1;
    }

    std::cout << "buffer read as - "<<read_buffer<<std::endl;

    close(fd);
    return 0;
}
Jun 20 16:03:51 kernel: [356787.943092] kernel_test:proc_entry_write
Jun 20 16:03:51 kernel: [356787.943554] kernel_test:proc_entry_write:offset = 0, count=0
Jun 20 16:03:51 kernel: [356787.943944] kernel_test:proc_entry_write:seqfile
Jun 20 16:03:51 kernel: [356787.944344] kernel_test:proc_entry_write:kmem
Jun 20 16:03:51 kernel: [356787.944978] kernel_test:proc_entry_seq_show
Jun 20 16:03:51 kernel: [356787.945408] kernel_test:proc_entry_seq_show:s->private=ee600600