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

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

问题描述

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

内核模块:

#include #include #include #include #include #include #include #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 .
", 任务);如果(任务 == NULL){printk("无法从用户程序中找到PID
");返回0;}send_sig_info(SIGIO, &sinfo, task);返回0;}void cleanup_module(){printk(KERN_ALERT"
再见世界

");}

用户空间代码:

#include #include #include #include 无效信号处理程序(int signum){if (signum == SIGIO) printf("SIGIO
");返回;}int main(){国际我= 1;信号(SIGIO,signal_handler);printf("我的 PID 是 %d.
", getpid());当我);返回0;}

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

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

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

还有别的办法吗?如果没有,那么任何人都可以帮我做到这一点吗?我是 c 编程新手,直接玩内核模块,所以对我来说很难.

解决方案

查看你给出的代码,看来你要处理SIGIO信号

这是我试图解决您的问题,

signal_kernel.c 文件:

#include #include #include #include #include #include #include #include #include #include #定义最大10MODULE_LICENSE("GPL");struct dentry *文件;静态 ssize_t write_conf_pid(struct file *file, const char *buf,size_t 计数,loff_t *位置){字符 temp_str[MAX];int ret;int pid = 0;struct siginfo sinfo;struct task_struct *task;/* 永远不要相信用户输入 */如果(计数 > MAX)返回 -EINVAL;如果(copy_from_user(temp_str,buf,MAX)!= 0)返回 -EFAULT;ret = sscanf(temp_str, "%d", &pid);如果(返回!= 1){pr_info("从用户读取PID值时出错");返回 -EINVAL;}pr_info("用户输入的pid %d
", 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
");返回-ENODEV;}ret = send_sig_info(SIGIO, &sinfo, task);如果 (ret <0)pr_info("发送信号出错
");返回计数;}静态 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;}void cleanup_module(){pr_info("
再见世界

");}

signal_user.c 文件:

#include #include #include #include 无效信号处理程序(int signum){如果(符号 == SIGIO)printf("SIGIO
");返回;}int main(){国际我= 1;信号(SIGIO,signal_handler);printf("我的 PID 是 %d.
", getpid());当我);返回0;}

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

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

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

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

有多种方法(sysfsmisc_char_devicechar device 等)来完成这项任务,但这会让你对使用 copy_from_user()copy_to_user()

请注意,signal_user.csignal_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 .
", task);

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

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

");
}

Userspace Code:

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

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

int main()
{
    int i = 1;
    signal(SIGIO, signal_handler);
    printf("My PID is %d.
", 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
", 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
");
        return -ENODEV;
    }
    ret = send_sig_info(SIGIO, &sinfo, task);
    if (ret < 0)
        pr_info("Error sending signal
");
    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("
GoodBye World

");
}

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
");
    return;
}

int main()
{
    int i = 1;
    signal(SIGIO, signal_handler);
    printf("My PID is %d.
", 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天全站免登陆