将数据从 linux 内核 space 复制到用户 space
copy data from linux kernel space to user space
我正在添加一个内核函数来修改 Specified pid of process 的 nice
和 prio
值。
代码如下:
SYSCALL_DEFINE5(mysetnice, pid_t, pid, int, flag, int, nicevalue, void __user *, prio, void __user *, nice)
{
if (pid < 0 || (flag != 1 && flag != 0)) {
return EFAULT;
}
if (nice == NULL || prio == NULL) {
return EFAULT;
}
struct task_struct *p;
for_each_process(p) {
if (p->pid == pid) {
if (flag == 1) {
set_user_nice(p, nicevalue);
printk("change nice=%d of pid=%d\n", nicevalue, pid);
}
printk("pid:%d,current nice:%d, prio:%d\n",pid,task_nice(p),task_prio(p));
copy_to_user(prio,(const void*)task_prio(p),sizeof(int));
copy_to_user(nice,(const void*)task_nice(p),sizeof(int));
return 0;
}
}
return EFAULT;
}
并且在用户范围内,我编写了一个这样的测试函数:
int main()
{
int pid = 0;
int flag = 0;
int nicevalue = 0;
int prio = 0;
int nice = 0;
int ret;
printf("please input the params: pid, flag, nicevalue\n");
while(~scanf("%d %d %d", &pid, &flag, &nicevalue))
{
ret = syscall(__NR_mysyscall, pid, flag, nicevalue, (void *)&prio, (void *)&nice);
if (ret != 0)
{
printf("syscall error! error code:%d\n", ret);
return 0;
}
printf("pid:%d, flag:%d, nicevalue:%d, prio:%d, nice:%d\n", pid, flag, nicevalue, prio + 100, nice);
}
return 0;
}
但是我发现我获取不到nice
值,而且prio
总是100
。那么如何将数据从内核范围复制到用户范围?
问题是,您必须提供源值的 地址 ,而不是值本身。尝试类似的东西:
int val = task_prio(p);
copy_to_user(prio,(const void*)&val,sizeof(int));
与 nice
相同,那么它应该按预期工作。
总体来说代码质量很差。
SYSCALL_DEFINE5(mysetnice, pid_t, pid, int, flag, int, nicevalue, void __user *, prio, void __user *, nice)
{
if (pid < 0 || (flag != 1 && flag != 0)) {
return EFAULT;
错误代码为负数。 IE。这应该是 -EFAULT,如在其他系统调用中所见。对于这种特殊情况,EFAULT 本身是一个非常糟糕的选择。通常 无效 参数导致 EINVAL。
}
if (nice == NULL || prio == NULL) {
return EFAULT;
}
struct task_struct *p;
for_each_process(p) {
你从哪里拿来的?
遍历进程列表的理由为 0。寻找一种翻译 pid -> task_struct * 的方法留作练习。提示:有些系统调用将 pid 作为参数。
遍历本身由于不充分(或更确切地说:缺少)锁定而不正确。
if (p->pid == pid) {
if (flag == 1) {
set_user_nice(p, nicevalue);
printk("change nice=%d of pid=%d\n", nicevalue, pid);
}
printk("pid:%d,current nice:%d, prio:%d\n",pid,task_nice(p),task_prio(p));
printk 中缺少日志级别。检查任何现有的 printk 以了解我的意思。
copy_to_user(prio,(const void*)task_prio(p),sizeof(int));
不仅没有错误检查,而且第二个参数的转换显然不正确。
copy_to_user(nice,(const void*)task_nice(p),sizeof(int));
return 0;
}
}
return EFAULT;
这个应该是ESRCH。
}
我正在添加一个内核函数来修改 Specified pid of process 的 nice
和 prio
值。
代码如下:
SYSCALL_DEFINE5(mysetnice, pid_t, pid, int, flag, int, nicevalue, void __user *, prio, void __user *, nice)
{
if (pid < 0 || (flag != 1 && flag != 0)) {
return EFAULT;
}
if (nice == NULL || prio == NULL) {
return EFAULT;
}
struct task_struct *p;
for_each_process(p) {
if (p->pid == pid) {
if (flag == 1) {
set_user_nice(p, nicevalue);
printk("change nice=%d of pid=%d\n", nicevalue, pid);
}
printk("pid:%d,current nice:%d, prio:%d\n",pid,task_nice(p),task_prio(p));
copy_to_user(prio,(const void*)task_prio(p),sizeof(int));
copy_to_user(nice,(const void*)task_nice(p),sizeof(int));
return 0;
}
}
return EFAULT;
}
并且在用户范围内,我编写了一个这样的测试函数:
int main()
{
int pid = 0;
int flag = 0;
int nicevalue = 0;
int prio = 0;
int nice = 0;
int ret;
printf("please input the params: pid, flag, nicevalue\n");
while(~scanf("%d %d %d", &pid, &flag, &nicevalue))
{
ret = syscall(__NR_mysyscall, pid, flag, nicevalue, (void *)&prio, (void *)&nice);
if (ret != 0)
{
printf("syscall error! error code:%d\n", ret);
return 0;
}
printf("pid:%d, flag:%d, nicevalue:%d, prio:%d, nice:%d\n", pid, flag, nicevalue, prio + 100, nice);
}
return 0;
}
但是我发现我获取不到nice
值,而且prio
总是100
。那么如何将数据从内核范围复制到用户范围?
问题是,您必须提供源值的 地址 ,而不是值本身。尝试类似的东西:
int val = task_prio(p);
copy_to_user(prio,(const void*)&val,sizeof(int));
与 nice
相同,那么它应该按预期工作。
总体来说代码质量很差。
SYSCALL_DEFINE5(mysetnice, pid_t, pid, int, flag, int, nicevalue, void __user *, prio, void __user *, nice)
{
if (pid < 0 || (flag != 1 && flag != 0)) {
return EFAULT;
错误代码为负数。 IE。这应该是 -EFAULT,如在其他系统调用中所见。对于这种特殊情况,EFAULT 本身是一个非常糟糕的选择。通常 无效 参数导致 EINVAL。
}
if (nice == NULL || prio == NULL) {
return EFAULT;
}
struct task_struct *p;
for_each_process(p) {
你从哪里拿来的?
遍历进程列表的理由为 0。寻找一种翻译 pid -> task_struct * 的方法留作练习。提示:有些系统调用将 pid 作为参数。
遍历本身由于不充分(或更确切地说:缺少)锁定而不正确。
if (p->pid == pid) {
if (flag == 1) {
set_user_nice(p, nicevalue);
printk("change nice=%d of pid=%d\n", nicevalue, pid);
}
printk("pid:%d,current nice:%d, prio:%d\n",pid,task_nice(p),task_prio(p));
printk 中缺少日志级别。检查任何现有的 printk 以了解我的意思。
copy_to_user(prio,(const void*)task_prio(p),sizeof(int));
不仅没有错误检查,而且第二个参数的转换显然不正确。
copy_to_user(nice,(const void*)task_nice(p),sizeof(int));
return 0;
}
}
return EFAULT;
这个应该是ESRCH。
}