2012-04-04 97 views
0

通常情况下,我们必须做这样从一个函数指针调用一个函数:从函数指针调用函数而不分配?

int foo() 
{ 
} 

int main() 
{ 
    int (*pFoo)() = foo; // pFoo points to function foo() 
    foo(); 
    return 0; 
} 

在Linux内核代码,sched_class有许多函数指针:

struct sched_class { 
     const struct sched_class *next; 

     void (*enqueue_task) (struct rq *rq, struct task_struct *p, int flags); 
     void (*dequeue_task) (struct rq *rq, struct task_struct *p, int flags); 
     void (*yield_task) (struct rq *rq); 
     bool (*yield_to_task) (struct rq *rq, struct task_struct *p, bool preempt); 
     ..... 
} 

pick_next_task功能,它定义一个名为class的本地实例sched_class,并直接调用其中的功能,而不用分配给具有相同签名的外部函数(从for_each_class开始):

static inline struct task_struct * 
pick_next_task(struct rq *rq) 
{ 
     const struct sched_class *class; 
     struct task_struct *p; 
    /* 
    * Optimization: we know that if all tasks are in 
    * the fair class we can call that function directly: 
    */ 
    if (likely(rq->nr_running == rq->cfs.h_nr_running)) { 
      p = fair_sched_class.pick_next_task(rq); 
      if (likely(p)) 
        return p; 
    } 

    for_each_class(class) { 
      p = class->pick_next_task(rq); 
      if (p) 
        return p; 
    } 

    BUG(); /* the idle class will always have a runnable task */ 
} 

这是因为在sched_class每个函数指针具有相同的名称与实际实现的功能,所以每次通话通过的sched_class函数指针做,它会自动找到在内核地址空间匹配的符号?

回答

5

for_each_class定义应该把它清除掉你

#define for_each_class(class) \ 
     for (class = sched_class_highest; class; class = class->next) 

如果你继续跟踪,sched_class_highest西港岛线落得这样的

#define sched_class_highest (&stop_sched_class) 
extern const struct sched_class stop_sched_class; 

/* 
* Simple, special scheduling class for the per-CPU stop tasks: 
*/ 
const struct sched_class stop_sched_class = { 
     .next     = &rt_sched_class, 

     .enqueue_task   = enqueue_task_stop, 
     .dequeue_task   = dequeue_task_stop, 
     .yield_task    = yield_task_stop, 

     .check_preempt_curr  = check_preempt_curr_stop, 

     .pick_next_task   = pick_next_task_stop, 
     .put_prev_task   = put_prev_task_stop, 

#ifdef CONFIG_SMP 
     .select_task_rq   = select_task_rq_stop, 
#endif 

    .set_curr_task   = set_curr_task_stop, 
    .task_tick    = task_tick_stop, 

    .get_rr_interval  = get_rr_interval_stop, 

    .prio_changed   = prio_changed_stop, 
    .switched_to   = switched_to_stop, 
}; 

现在你快乐吗? :)

0

每个sched_class结构,它包含的函数指针被初始化(否则,它可能是一个错误)。例如,公平调度class初始化为kernel/sched/fair.c(参见here):

const struct sched_class fair_sched_class = { 
     .next     = &idle_sched_class, 
     /* lots of assignments */ 
     .pick_next_task   = pick_next_task_fair, 
     /* etc. */ 
};