我正在寻找将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 <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");
}
用户空间代码:
#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;
}
现在,我总是运行用户空间程序来获取PID,然后我总是要在内核模块中编辑pid变量。
我找到了一种从用户空间访问内核空间信息的方法,反之亦然(即使用copy_from/to_user()
)
但我无法理解他们中的任何一个从用户空间获取PID,我必须在/dev
目录中创建文件并应该应用所有必需的函数来获取PID?
还有其他方法吗?如果没有,那么有人可以帮我这样做吗?我是c编程的新手,直接使用内核模块,所以对我来说很难。
答案 0 :(得分:3)
查看您提供的代码,似乎您想要处理SIGIO
信号
以下是我尝试解决您的问题,
signal_kernel.c
档案:
#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
档案:
#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;
}
编译并运行用户空间和内核空间程序后,使用debugfs
接口将PID值发送到内核空间,
$ insmod signal_kernel.ko
$ ./signal_user
My PID is 17633.
... # Process will run in loop due to while(1)
从另一个终端,向debugfs
接口提供PID,
$ echo 17633 > /sys/kernel/debug/pidconf
此任务有多种方式(sysfs
,misc_char_device
,char device
等),但这会让您简要了解如何使用copy_from_user()
和{{1 }}
请注意,copy_to_user()
和signal_user.c
中的错误处理很少。