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

Linux kernel 无法将结构从模块复制到用户空间,linux-kernel,linux-device-driver,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_

这是我的内核级模块:

#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);
#包括
#包括
#包括
#包括
#包括
静态结构miscdevice my_dev;
结构时间检查
{
时间电视秒;
时间-电视-秒-天;
龙国际电视台;
长国际电视日;
}时间;
ssize_t read_函数(结构文件*文件指针、字符*缓冲区、大小计数、loff_t*偏移量);
int open_函数(结构索引节点*节点指针,结构文件*文件指针);
静态常量结构文件\u操作文件\u op={
.read=读取函数,
.open=打开功能,
};
int open_函数(结构索引节点*节点指针,结构文件*文件指针)
{
printk(“打开了文件模块”\n);
返回0;
}
ssize_t read_函数(结构文件*文件指针、字符*缓冲区、大小计数、loff_t*偏移量)
{
int error_no=0;
struct timespec获取\u时间;
结构时间检查时间;
如果(访问\u正常(验证\u读取、缓冲区、2*sizeof(struct timespec)))
{ 
struct timespec cur_time=当前内核时间();
printk(“当前内核时间:\n%lld%lld\n”,(长)(cur_-time.tv_-sec),(长)(cur_-time.tv_-nsec));
getnstimeofday(&gets_时间);
printk(“getnstimeofday:\n%lld%lld\n”,(long long)(获取时间.tv秒),(long long)(获取时间.tv秒));
time_s.tv_sec_ker=cur_time.tv_sec;
time_s.tv_nsec_ker=cur_time.tv_nsec;
time_.tv_sec_nsday=获取time.tv_sec;
time\u.tv\u nsec\u nsday=获取time.tv\u nsec;
printk(“复制的当前内核时间:\n%lld%lld\n”,(long-long)(时间-美国电视秒),(long-long)(时间-美国电视秒));
printk(“getnstimepfday\u复制:\n%lld%lld\n”,(长)(美国电视台时间秒日),(长)(美国电视台时间日));
if(复制到用户(缓冲区、时间、大小)
错误号=-EFAULT;
}
其他的
{
错误号=-EFAULT;
}
返回错误号;
}
int init_函数(void)
{
内部检索;
my_dev.minor=MISC_DYNAMIC_minor;
my_dev.name=“mytime”;
my_dev.fops=&file\u op;
retval=misc_register(&my_dev);
if(retval)返回retval;
printk(“获得次要%i\n”,我的开发次要);
返回0;
}
void exit_函数(void)
{
杂项注销(和我的开发);
}
模块_init(init_函数);
模块退出(退出功能);
这是我的用户级功能:

#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;
}
#包括
#包括
#包括
#包括
结构时间检查
{
时间电视秒;
时间-电视-秒-天;
龙国际电视台;
长国际电视日;
}钛;
int main()
{
文件*fd;
整数计数;
结构时间\检查时间;
/*开放式设备*/
fd=fopen(“/dev/mytime”,“r”);
/*从设备读取*/
计数=fread(&time,sizeof(time),1,fd);
printf(“返回值%d\n”,计数);
printf(“时间大小:%ld\n”,大小(时间));
printf(“克尔秒:%ld\nker秒:%ld\nnsday秒:%ld\nnsday秒:%ld\n”,time.tv秒,time.tv秒,time.tv秒,time.tv秒,time.tv秒,time.tv秒,time.tv秒;
/*闭合装置*/
fclose(fd);
返回0;
}
但我无法复制结构。我不明白我哪里做错了。 它在用户级别打印一些垃圾值

返回值0

时间:32

克鲁秒:0

ker_nsec:4196144

NSU第二天:0

NSU nsec:4195696


有谁能告诉我,要成功复制结构,我应该做些什么更改吗?如果您给出了错误的返回值

read_函数应该返回您复制到用户空间的确切数字

返回错误号,因此如果复制成功,它应该是结构“time”的大小

输出:

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;
}

您给出了错误的返回值

read_函数应该返回您复制到用户空间的确切数字

返回错误号,因此如果复制成功,它应该是结构“time”的大小

输出:

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;
}
可能的副本。简而言之:您的.read方法应该返回已读取的字节数,而不是纯零。的可能重复。简而言之:您的.read方法应该返回已读取的字节数,而不是纯零。