无法将结构从模块复制到用户空间

时间:2017-10-22 17:54:47

标签: linux-kernel linux-device-driver

这是我在内核级别的模块:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/miscdevice.h>


static struct miscdevice my_dev;

struct time_check
{
time_t tv_sec_ker;
time_t tv_sec_nsday;
long int tv_nsec_ker;
long int tv_nsec_nsday;
}time;


ssize_t read_function(struct file *file_pointer, char *buffer, size_t count, loff_t *offset);

int open_function(struct inode *node_pointer,struct file *file_pointer);


static const struct file_operations file_op = {
        .read = read_function,
        .open = open_function,
};

int open_function(struct inode *node_pointer,struct file *file_pointer)
{
        printk(" opened the file module\n");
        return 0;
}

ssize_t read_function(struct file *file_pointer,char *buffer,size_t count,loff_t *offset)
{


    int error_no=0;
struct timespec gets_time;
struct time_check time_s;
if(access_ok(VERIFY_READ,buffer,2*sizeof(struct timespec)))
{ 
struct timespec cur_time=current_kernel_time();         
printk("current_kernel_time:\n%lld  %lld\n",(long long)(cur_time.tv_sec),(long long)(cur_time.tv_nsec));

getnstimeofday(&gets_time);
            printk("getnstimeofday:\n%lld  %lld\n",(long long)(gets_time.tv_sec),(long long)(gets_time.tv_nsec));


            time_s.tv_sec_ker=cur_time.tv_sec;
            time_s.tv_nsec_ker=cur_time.tv_nsec;
            time_s.tv_sec_nsday=gets_time.tv_sec;
            time_s.tv_nsec_nsday=gets_time.tv_nsec;

            printk("current_kernel_time_copied:\n%lld  %lld\n",(long long)(time_s.tv_sec_ker),(long long)(time_s.tv_nsec_ker));
            printk("getnstimepfday_copied:\n%lld  %lld\n",(long long)(time_s.tv_sec_nsday),(long long)(time_s.tv_nsec_nsday));

            if(copy_to_user(buffer,&time_s,sizeof(time_s)))
                    error_no=-EFAULT;

    }
    else
    {
    error_no=-EFAULT;
    }
    return error_no;



}
int init_function(void)
{
    int retval;
    my_dev.minor = MISC_DYNAMIC_MINOR;
    my_dev.name = "mytime";
    my_dev.fops = &file_op;
    retval = misc_register(&my_dev);
    if (retval) return retval;
    printk("got minor %i\n",my_dev.minor);
    return 0;
}


void exit_function(void)
{

        misc_deregister(&my_dev);
}

module_init(init_function);
module_exit(exit_function);

这是我的用户级功能:

#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include <sys/stat.h>

struct time_check
{
time_t tv_sec_ker;
time_t tv_sec_nsday;
long int tv_nsec_ker;
long int tv_nsec_nsday;
}ti;

int main()
{
        FILE *fd;
        int count;
        struct time_check time;

        /* open device */
        fd = fopen("/dev/mytime","r");

        /* read from device */
        count =fread(&time,sizeof(time),1,fd);
        printf("Return value %d\n", count);
        printf("size of time:%ld\n",sizeof(time));
        printf("ker_sec:%ld\nker_nsec:%ld\nnsday_sec:%ld\nnsday_nsec:%ld\n",time.tv_sec_ker,time.tv_nsec_ker,time.tv_sec_nsday,time.tv_nsec_nsday);

        /* close device */
        fclose(fd);

        return 0;
}

但我无法复制结构。我无法理解我哪里做错了。 它在用户级别打印一些垃圾值。

返回值0

时间大小:32

ker_sec:0

ker_nsec:4196144

nsday_sec:0

nsday_nsec:4195696

任何人都可以告诉我应该做些什么更改才能成功复制结构

1 个答案:

答案 0 :(得分:0)

您给出错误的返回值。

read_function应返回您复制到用户空间的确切数字。

你返回error_no,所以如果复制成功,它应该是struct“time_s”的大小。

输出:

Return value 1
size of time:32
ker_sec:1508833722
ker_nsec:745536502
nsday_sec:1508833722
nsday_nsec:746151801

源代码:

ssize_t read_function(struct file *file_pointer,char *buffer,size_t count,loff_t *offset)
{
    int error_no=0;
    struct timespec gets_time;
    struct time_check time_s;
    if(access_ok(VERIFY_READ,buffer,2*sizeof(struct timespec)))
    {
        struct timespec cur_time=current_kernel_time();
        printk("current_kernel_time:\n%lld  %lld\n",(long long)(cur_time.tv_sec),(long long)(cur_time.tv_nsec));

        getnstimeofday(&gets_time);
        printk("getnstimeofday:\n%lld  %lld\n",(long long)(gets_time.tv_sec),(long long)(gets_time.tv_nsec));

        time_s.tv_sec_ker=cur_time.tv_sec;
        time_s.tv_nsec_ker=cur_time.tv_nsec;
        time_s.tv_sec_nsday=gets_time.tv_sec;
        time_s.tv_nsec_nsday=gets_time.tv_nsec;

        printk("current_kernel_time_copied:\n%lld  %lld\n",(long long)(time_s.tv_sec_ker),(long long)(time_s.tv_nsec_ker));
        printk("getnstimepfday_copied:\n%lld  %lld\n",(long long)(time_s.tv_sec_nsday),(long long)(time_s.tv_nsec_nsday));

        if(!copy_to_user(buffer,&time_s,sizeof(time_s)))
        {
                error_no = sizeof(time_s);
        }       
        else
        {
                error_no=-EFAULT;
        }

    }
    else
    {
        error_no=-EFAULT;
    }

    printk("=== copy number ====%d", error_no);
    return error_no;
}