我正在使用systemcall和copy_to_user创建代码以将内核中的字符串传输到usermode
这是我的代码
内核
#include<linux/kernel.h>
#include<linux/syscalls.h>
#include<linux/sched.h>
#include<linux/slab.h>
#include<linux/errno.h>
asmlinkage int sys_getProcTagSysCall(pid_t pid, char **tag){
printk("getProcTag system call \n\n");
struct task_struct *task= (struct task_struct*) kmalloc(sizeof(struct task_struct),GFP_KERNEL);
read_lock(&tasklist_lock);
task = find_task_by_vpid(pid);
if(task == NULL )
{
printk("corresponding pid task does not exist\n");
read_unlock(&tasklist_lock);
return -EFAULT;
}
read_unlock(&tasklist_lock);
printk("Corresponding pid task exist \n");
printk("tag is %s\n" , task->tag);
/*
task -> tag : string is stored in task->tag (ex : "abcde")
this part is well worked
*/
if(copy_to_user(*tag, task->tag, sizeof(char) * task->tag_length) !=0)
;
return 1;
}
and this is user
#include<stdio.h>
#include<stdlib.h>
int main()
{
char *ret=NULL;
int pid = 0;
printf("PID : ");
scanf("%4d", &pid);
if(syscall(339, pid, &ret)!=1) // syscall 339 is getProcTagSysCall
printf("pid %d does not exist\n", pid);
else
printf("Corresponding pid tag is %s \n",ret); //my output is %s = null
return 0;
}
实际上我并不了解copy_to_user。但我认为copy_to_user(* tag,task-&gt; tag,sizeof(char)* task-&gt; tag_length)的操作方式与此代码类似 所以我使用像上面的copy_to_user
#include<stdio.h>
int re();
void main(){
char *b = NULL;
if (re(&b))
printf("success");
printf("%s", b);
}
int re(char **str){
char *temp = "Gdg";
*str = temp;
return 1;
}
答案 0 :(得分:0)
我通过在用户
中创建malloc解决了我的问题我改变了
char *b = NULL;
到
char *b = (char*)malloc(sizeof(char) * 100)
我不知道为什么这项工作正常。但是我猜copy_to_user获取字节数作为第三个参数所以我应该在分配值之前使用malloc
我不知道。任何知道为什么添加malloc正常工作的人都告诉我
答案 1 :(得分:0)
从修复它的方式来看,这一点非常明显。 copy_to_user()
只会在两个内存区域之间复制数据 - 一个只能由内核访问,另一个内存也可供用户访问。但是,它不会处理任何内存分配。必须已经分配了用户空间缓冲区,您应该将此缓冲区的地址传递给内核。
你可以改变的另一件事是改变你的系统调用以使用指向char的普通指针而不是指向无用的指针。
另请注意,您在内核代码中泄漏了内存。您使用task_struct
为kmalloc
分配内存,然后在调用find_task_by_vpid()
时覆盖您对此内存的唯一指针,并且永远不会释放此内存。 find_task_by_vpid()
将返回一个指向已存在于内存中的task_struct的指针,因此不需要为此分配任何缓冲区。
答案 2 :(得分:0)
这是某种大学作业吗?
asmlinkage int sys_getProcTagSysCall(pid_t pid, char **tag){
这是什么,Linux 2.6?什么是**而不是*?
printk("getProcTag system call \n\n");
有点糟糕。所有字符串都应该是前缀。
struct task_struct *task= (struct task_struct*) kmalloc(sizeof(struct task_struct),GFP_KERNEL);
这里发生了什么?使用malloc毫无意义,如果你使用malloc,你应该使用sizeof(* task),但你不应该首先使用malloc。你想要找到一个任务,事实上你只需要在几行之后覆盖这个指针的值。
read_lock(&tasklist_lock);
task = find_task_by_vpid(pid);
find_task_by_vpid需要RCU。内核会告诉你,如果你启用了调试。
if(task == NULL )
{
printk("corresponding pid task does not exist\n");
read_unlock(&tasklist_lock);
return -EFAULT;
}
read_unlock(&tasklist_lock);
所以......你解锁......但你没有得到任何关于任务的参考。
printk("Corresponding pid task exist \n");
printk("tag is %s\n" , task->tag);
...换句话说,当你执行任务 - >标签时,任务可能已经消失。有什么要求可以访问 - &gt;标记本身?
if(copy_to_user(*tag, task->tag, sizeof(char) * task->tag_length) !=0)
;
这是什么? sizeof(char)保证为1。
我对这整个事业感到很困惑。
当你有一个系统调用将数据复制到用户空间时,在调用之前未知数据量,teh syscall接受缓冲区和它的大小。如果您要复制的东西不适合,则可以返回相应的错误。
但是,首先使用系统调用看起来不正确。在linux中,每个任务数据暴露在/ proc / pid /中的用户空间。弄清楚如何将文件添加到proc很容易,并留给读者练习。