【问题标题】:How to modify task_struct in Linux Kernel 3.8.0如何在 Linux Kernel 3.8.0 中修改 task_struct
【发布时间】:2013-10-20 17:41:22
【问题描述】:

我目前正在从事一个涉及修改 linux 优先级实施方式的项目。

为此,我有:

  • 自定义系统调用:修改进程的 task_struct 以更改其优先级

  • 修改过的 kernel/sched/fair.c

  • 修改了标准 task_struct 以添加新字段

    虽然自定义系统调用有效:它被正确调用并打印到 dmesg,fair.c 文件似乎没有考虑更改。

original fair.c

对 fair.c 的更改:

 /*
  * move_task - move a task from one runqueue to another runqueue.
  * Both runqueues must be locked.
  */
 static void move_task(struct task_struct *p, struct lb_env *env)
 {
         deactivate_task(env->src_rq, p, 0);
         if (p->prio_per_cpu)
         {            
            p->rt_priority = p->smp_prio[env->dst_cpu];
            printk(KERN_EMERG "We are in move_task function");
         }
         set_task_cpu(p, env->dst_cpu);
         activate_task(env->dst_rq, p, 0);
         check_preempt_curr(env->dst_rq, p, 0);
 }

p->prio_per_cpu 在系统调用中设置为 1,但 move_task 函数似乎看不到它。

系统调用:

/* system call to set the new field in 
 * task struct 'smp_prio' that allows 
 * one priority per processor on SMP machines
 */

asmlinkage long sys_set_smp_prio(pid_t pid, const char *smp_prio)
{
 struct pid *pid_struct;
 struct task_struct *p;

 pid_struct = find_get_pid(pid);
 p = pid_task(pid_struct,PIDTYPE_PID);
 p->prio_per_cpu = 1;
 p->smp_prio = (char*) smp_prio;
 printk(KERN_EMERG "SMP priorities are correctly set \n");
 return 1;
}

我收到系统调用 printk 消息。

originaltask_struct

修改后的task_struct:

#define INIT_TASK(tsk)  \
 {                                                                       \
     .state          = 0,                                            \
     .stack          = &init_thread_info,                            \
     .usage          = ATOMIC_INIT(2),                               \
     .flags          = PF_KTHREAD,                                   \
     .prio_per_cpu   = 0,                                            \
     .smp_prio       = NULL,                                         \
     .prio           = MAX_PRIO-20,                                  \
     .static_prio    = MAX_PRIO-20,                                  \
     .normal_prio    = MAX_PRIO-20,                                  \
     .policy         = SCHED_NORMAL,                                 \
     .cpus_allowed   = CPU_MASK_ALL,                                 \
     .nr_cpus_allowed= NR_CPUS,                                      \
     .mm             = NULL,                                         \
     .active_mm      = &init_mm,                                     \
     .se             = {                                             \
             .group_node     = LIST_HEAD_INIT(tsk.se.group_node),    \
     },                                                              \
     .rt             = {                                             \
             .run_list       = LIST_HEAD_INIT(tsk.rt.run_list),      \
             .time_slice     = RR_TIMESLICE,                         \
     },         
     [...]

当我修改 move_task() 以无条件打印一条消息时,它确实打印了该消息。

我确定 move_task 使用系统调用修改的线程的 task_struct 参数调用,因为我通过设置 cpusets(位掩码)手动强制线程迁移,而 move_task 是执行从一个 cpu 迁移到另一个 cpu 的代码。

为什么自定义系统调用所做的更改在 move_task() 函数中无效?

感谢您的帮助!

【问题讨论】:

  • 我想到的第一个明显的问题是,您是否在if (p->prio_per_cpu) 行设置了一个断点,以查看评估时p->prio_per_cpu 的值是多少。如果是0,则永远不会进入打印功能。
  • deactivate_task(env->src_rq, p, 0);p 做了什么?
  • 另外,看起来p 的本地范围为sys_set_smp_prio() 是吗?
  • deactivate_task 将 p 表示的任务从它实际所在的运行队列中移除
  • 对 task_struct 做了哪些更改?可以发一下吗?

标签: c linux-kernel scheduling smp


【解决方案1】:

我很久以前就找到了解决方案,但只是为了记录:我正在使用实时线程测试这个新的内核设施。它们不是由 CFS 调度程序安排的 (fair.c)

【讨论】:

  • 如果您找到了解决方案,请告诉它 - 否则这对其他人没有任何价值,应该删除该问题。
  • 对不起,如果我不清楚,解决方案在我的帖子中:实时程序不是使用 fair.c 安排的,因此 move_task() 没有被调用...
【解决方案2】:

该函数中本地定义的struct task_struct *p;

asmlinkage long sys_set_smp_prio(pid_t pid, const char *smp_prio)
{
 struct pid *pid_struct;
 struct task_struct *p;  //THIS COPY OF task_struct *p HAS NO CONNECTION...

 pid_struct = find_get_pid(pid);
 task = pid_task(pid_struct,PIDTYPE_PID);
 p->prio_per_cpu = 1;
 p->smp_prio = (char*) smp_prio;
 printk(KERN_EMERG "SMP priorities are correctly set \n");
 return 1;
}   

与传递的参数struct task_struct *p 没有可见的关系(至少在提供的代码中)

static void move_task(struct task_struct *p, struct lb_env *env) //TO THIS ONE
 {
         deactivate_task(env->src_rq, p, 0);
         if (p->prio_per_cpu)  //If this value is zero, printk will never be called.
         {            
            p->rt_priority = p->smp_prio[env->dst_cpu];
            printk(KERN_EMERG "We are in move_task function");
         }
         set_task_cpu(p, env->dst_cpu);
         activate_task(env->dst_rq, p, 0);
         check_preempt_curr(env->dst_rq, p, 0);
 }  

也就是说,我看不到您在 sys_set_smp_prio() 内调用 move_task() 的位置,其更新值为 p->prio_per_cpu = 1;。会不会是这个问题?

【讨论】:

  • @rykker 对不起,我发布的代码有误,我刚刚编辑了它。代码编译正确。
  • 那么,你的问题得到解答了吗?
  • 我的意思是我的代码编译正确,而访问 p->prio_per_cpu 不会出现这种情况(会出现段错误),只是在 stackoverflow 上复制代码时出现错误.
  • @MehdiSouihed ryyker 所指的是move_task 中的参数p 可能属于与您在函数sys_set_smp_prio 中修改prio_per_cpu 字段的任务不同的任务。如果你不这么认为,请打印move_task里面的PID,并交叉检查你在sys_set_smp_prio中修改的任务的PID是否也打印在那里。
  • @VivekS 感谢您的评论。我忘了提到我有一个测试程序,它通过将它们连续固定在不同的 cpu(cpu 位掩码)上来强制线程迁移。我确信这可行,因为我可以使用trace-cmdkernelshark 将其可视化。 move_task() 必须在线程从一个 cpu 迁移到另一个 cpu 期间调用。
猜你喜欢
  • 1970-01-01
  • 2013-10-25
  • 1970-01-01
  • 2013-11-21
  • 1970-01-01
  • 2021-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多