copy_from_user()的任何示例?内核和用户空间 [英] any example of copy_from_user() ? kernel and userspace

查看:146
本文介绍了copy_from_user()的任何示例?内核和用户空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找将PID值从用户空间复制到内核空间的方法,这是我的代码捕捉.

内核模块:

 <代码> #include< linux/module.h>#include< linux/kernel.h>#include< linux/init.h>#include< asm/siginfo.h>#include< linux/rcupdate.h>#include< linux/sched.h>#include< linux/uaccess.h>#include MODULE_LICENSE("GPL");struct siginfo sinfo;pid_t pid;struct task_struct *task;int init_module(){memset(& sinfo,0,sizeof(struct siginfo));sinfo.si_signo = SIGIO;sinfo.si_code = SI_USER;pid = 5218;//每次有新的PID//task = find_task_by_vpid(pid);我还在研究新版本和旧版本的UBUNTU,所以这就是为什么任务= pid_task(find_vpid(pid),PIDTYPE_PID);printk(%d.\ n",任务);if(task == NULL){printk(从用户程序中找不到PID \ r \ n");返回0;}send_sig_info(SIGIO, &sinfo, task);返回0;}无效cleanup_module(){printk(KERN_ALERT"\ nGoodBye World \ n \ n");} 

用户空间代码:

  #include< stdio.h>#include< stdlib.h>#include< signal.h>#include< string.h>无效signal_handler(int signum){if(signum == SIGIO)printf("SIGIO \ r \ n");返回;}int main(){int i = 1;signal(SIGIO,signal_handler);printf(我的PID是%d.\ n",getpid());当我);返回0;} 

现在,在这里我总是运行用户空间程序来获取PID,然后我总是必须在内核模块中编辑pid变量.

我找到了一种从用户空间访问信息到内核空间以及反之亦然的方法(即,使用 copy_from/to_user())

但是我不能理解它们中的任何一个用于从用户空间获取PID,我必须在/dev 目录中创建文件,并且应该应用所有必需的功能来获取PID?

还有其他方法吗?如果没有,那么任何人都可以帮我做到这一点吗?我是C语言编程的新手,可以直接使用内核模块,所以这对我来说很难.

解决方案

查看您提供的代码,看来您想处理 SIGIO 信号

这是我为您解决问题的尝试,

signal_kernel.c 文件:

  #include< linux/module.h>#include< linux/kernel.h>#include< linux/init.h>#include< asm/siginfo.h>#include #include< linux/sched.h>#include< linux/uaccess.h>#include< linux/signal.h>#include< linux/debugfs.h>#include< linux/pid.h>#定义MAX 10MODULE_LICENSE("GPL");struct dentry *文件;静态ssize_t write_conf_pid(结构文件* file,const char * buf,size_t计数,loff_t *位置){char temp_str [MAX];诠释int pid = 0;struct siginfo sinfo;struct task_struct *任务;/*永远不要信任用户输入*/如果(count> MAX)返回-EINVAL;如果(copy_from_user(temp_str,buf,MAX)!= 0)返回-EFAULT;ret = sscanf(temp_str,%d",& pid);如果(ret!= 1){pr_info(读取用户PID值时出错");返回-EINVAL;}pr_info(用户输入的pid%d \ n",pid);memset(& sinfo,0,sizeof(struct siginfo));sinfo.si_signo = SIGIO;sinfo.si_code = SI_USER;任务= pid_task(find_vpid(pid),PIDTYPE_PID);如果(任务== NULL){pr_info(无法从用户程序中找到PID \ r \ n");返回-ENODEV;}ret = send_sig_info(SIGIO,& sinfo,task);如果(ret< 0)pr_info(发送信号时出错\ n");返回计数;}静态const struct file_operations my_fops = {.write = write_conf_pid,};int init_module(){/*只有root可以写入此文件*/file = debugfs_create_file("pidconf",0200,NULL,NULL,& my_fops);返回0;}无效cleanup_module(){pr_info("\ nGoodBye World \ n \ n");} 

signal_user.c 文件:

  #include< stdio.h>#include< stdlib.h>#include< signal.h>#include< string.h>无效signal_handler(int signum){如果(signum == SIGIO)printf("SIGIO \ r \ n");返回;}int main(){int i = 1;signal(SIGIO,signal_handler);printf(我的PID是%d.\ n",getpid());当我);返回0;} 

编译并运行用户空间和内核空间程序后,使用 debugfs 接口将PID值发送到内核空间,

  $ insmod signal_kernel.ko$ ./signal_user我的PID是17633....#由于while(1),进程将循环运行 

在另一个终端上,将PID提供给 debugfs 接口

  $ echo 17633>/sys/内核/调试/pidconf 

有多种方法( sysfs misc_char_device char device 等),但这将为您提供有关的简要信息使用 copy_from_user()copy_to_user()

请注意,在 signal_user.c signal_kernel.c 中几乎没有错误处理.

I am looking for copying PID value from User space to Kernel space, here is my code snaps.

Kernel Module:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/siginfo.h>
#include <linux/rcupdate.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <linux/signal.h>

MODULE_LICENSE ("GPL");

struct siginfo sinfo;
pid_t pid;
struct task_struct *task;

int init_module() 
{
    memset(&sinfo, 0, sizeof(struct siginfo));
    sinfo.si_signo = SIGIO;
    sinfo.si_code = SI_USER;
    pid = 5218; // Everytime a new PID 
    // task = find_task_by_vpid(pid); I am also working on new and old version of UBUNTU so thats why this is here
    task = pid_task(find_vpid(pid), PIDTYPE_PID); 
    printk("%d .\n", task);

    if(task == NULL) {
        printk("Cannot find PID from user program\r\n");
        return 0;
    }

    send_sig_info(SIGIO, &sinfo, task);
    return 0;
}
void cleanup_module () 
{
    printk(KERN_ALERT"\nGoodBye World\n\n");
}

Userspace Code:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>

void signal_handler(int signum)
{
    if (signum == SIGIO) printf("SIGIO\r\n"); return;
}

int main()
{
    int i = 1;
    signal(SIGIO, signal_handler);
    printf("My PID is %d.\n", getpid());
    
    while (i);
    return 0;
}

Now, here I am always running user space program to get PID and then I always have to edit the pid variable in Kernel module.

I found one way to access information from user space into Kernel space and vice-versa (i.e., using copy_from/to_user() )

But I am unable to understand either of them for getting a PID from user space, I have to make file in /dev directory and should apply all the required functions for just getting PID?

Is there any other way? if not, then can anyone please help me to do this? I am new in c programming and playing with kernel module directly so its hard for me.

解决方案

Look into code you have given, it seems that you want to handle SIGIO signal

Here is my attempt to solve your problem,

signal_kernel.c file :

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/siginfo.h>
#include <linux/rcupdate.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <linux/signal.h>
#include <linux/debugfs.h>
#include <linux/pid.h>

#define MAX 10

MODULE_LICENSE("GPL");

struct dentry *file;

static ssize_t write_conf_pid(struct file *file, const char *buf,
            size_t count, loff_t *position)
{
    char temp_str[MAX];
    int ret;
    int pid = 0;
    struct siginfo sinfo;
    struct task_struct *task;

    /* NEVER TRUST USER INPUT */
    if (count > MAX)
        return -EINVAL;

    if (copy_from_user(temp_str, buf, MAX) != 0)
        return -EFAULT;

    ret = sscanf(temp_str, "%d", &pid);
    if (ret != 1) {
        pr_info("Error in reading PID value from user");
        return -EINVAL;
    }

    pr_info("User entered pid %d\n", pid);
    memset(&sinfo, 0, sizeof(struct siginfo));
    sinfo.si_signo = SIGIO;
    sinfo.si_code = SI_USER;
    task = pid_task(find_vpid(pid), PIDTYPE_PID);
    if (task == NULL) {
        pr_info("Cannot find PID from user program\r\n");
        return -ENODEV;
    }
    ret = send_sig_info(SIGIO, &sinfo, task);
    if (ret < 0)
        pr_info("Error sending signal\n");
    return count;
}

static const struct file_operations my_fops = {
    .write = write_conf_pid,
};

int init_module()
{
    /* Only root can write to this file */
    file = debugfs_create_file("pidconf", 0200, NULL, NULL, &my_fops);
    return 0;
}

void cleanup_module()
{
    pr_info("\nGoodBye World\n\n");
}

signal_user.c file :

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>

void signal_handler(int signum)
{
    if (signum == SIGIO)
        printf("SIGIO\r\n");
    return;
}

int main()
{
    int i = 1;
    signal(SIGIO, signal_handler);
    printf("My PID is %d.\n", getpid());
    while (i);
    return 0;
}

After compiling and running both user space and kernel space program, use debugfs interface to send PID value to Kernel space,

$ insmod signal_kernel.ko
$ ./signal_user 
My PID is 17633.

... # Process will run in loop due to while(1)

From another terminal, provide PID to debugfs interface,

$ echo 17633 > /sys/kernel/debug/pidconf

There are various ways (sysfs, misc_char_device, char device etc.) to this task, but this will give you brief idea about using copy_from_user() and copy_to_user()

Please note that there is little error handling done in signal_user.c and signal_kernel.c.

这篇关于copy_from_user()的任何示例?内核和用户空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆