如何在Linux Kernel 3.8.0中修改task_struct

时间:2013-10-20 17:41:23

标签: c linux-kernel scheduling smp

我目前正致力于一个涉及修改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消息。

original task_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 使用syscall修改的线程的task_struct参数调用,因为我通过设置cpusets(bitmask)手动强制执行线程迁移,而move_task是执行从一个cpu到另一个cpu的迁移的代码。

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

感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

此函数中本地定义的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);
 }  

也就是说,我没有在move_task()内看到sys_set_smp_prio()p->prio_per_cpu = 1;的更新值。这可能是问题吗?

答案 1 :(得分:0)

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