2012-04-04 6 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); 
     ..... 
} 

In pick_next_task функции, она определяет локальный экземпляр sched_class с именем 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. */ 
}; 
Смежные вопросы