pdflush代码分析

来源:互联网 发布:淘宝卖家怎样设置运费 编辑:程序博客网 时间:2024/05/24 02:22
前文对pdflush的基本概念和使用方法做了简单的介绍,下面将详细介绍pdflush在Linux内核中的实现,本文的分析基于2.6.10内核。

基本调用流程

如下图为pdflush的基本调用流程,在模块初始化的时候会启动一个pdflush线程,__pdflush()函数为线程函数,具体工作在该函数中完成。


线程池

如下为该函数的具体实现,该函数实际上实现了一个线程池的功能,具体工作由pdflu_work关联的函数完成:
static int __pdflush(struct pdflush_work *my_work){current->flags |= PF_FLUSHER;my_work->fn = NULL;my_work->who = current;          INIT_LIST_HEAD(&my_work->list);  //链表项初始化spin_lock_irq(&pdflush_lock);nr_pdflush_threads++;            //线程计数for ( ; ; ) {struct pdflush_work *pdf;set_current_state(TASK_INTERRUPTIBLE);list_move(&my_work->list, &pdflush_list);my_work->when_i_went_to_sleep = jiffies;spin_unlock_irq(&pdflush_lock);schedule();   //将自己调度出去if (current->flags & PF_FREEZE) {refrigerator(PF_FREEZE);spin_lock_irq(&pdflush_lock);continue;}spin_lock_irq(&pdflush_lock);if (!list_empty(&my_work->list)) {printk("pdflush: bogus wakeup!\n");my_work->fn = NULL;continue;}if (my_work->fn == NULL) {printk("pdflush: NULL work function\n");continue;}spin_unlock_irq(&pdflush_lock);(*my_work->fn)(my_work->arg0);   //具体的刷写函数,由pdflush_operation函数指定/* * Thread creation: For how long have there been zero * available threads? */if (jiffies - last_empty_jifs > 1 * HZ) {/* unlocked list_empty() test is OK here */if (list_empty(&pdflush_list)) {/* unlocked test is OK here */if (nr_pdflush_threads < MAX_PDFLUSH_THREADS)start_one_pdflush_thread();}}spin_lock_irq(&pdflush_lock);my_work->fn = NULL;/* * Thread destruction: For how long has the sleepiest * thread slept? */if (list_empty(&pdflush_list))continue;if (nr_pdflush_threads <= MIN_PDFLUSH_THREADS)continue;pdf = list_entry(pdflush_list.prev, struct pdflush_work, list);if (jiffies - pdf->when_i_went_to_sleep > 1 * HZ) {/* Limit exit rate */pdf->when_i_went_to_sleep = jiffies;break;/* exeunt */}}nr_pdflush_threads--;spin_unlock_irq(&pdflush_lock);return 0;}

如下是pdflush_work结构体的代码:
struct pdflush_work {struct task_struct *who;/* 具体线程 */void (*fn)(unsigned long);/* A callback function */unsigned long arg0;/* An argument to the callback */struct list_head list;/* On pdflush_list, when idle */unsigned long when_i_went_to_sleep;};

另外一个关键的函数是pdflush_operation,该函数实现对线程池中线程的唤醒,并实现对刷写工作的初始化。
int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0){unsigned long flags;int ret = 0;if (fn == NULL)BUG();/* fn是具体的刷写处理函数,如果要唤醒线程池,该函数自然不能为空 */spin_lock_irqsave(&pdflush_lock, flags);if (list_empty(&pdflush_list)) {spin_unlock_irqrestore(&pdflush_lock, flags);ret = -1;} else {struct pdflush_work *pdf;pdf = list_entry(pdflush_list.next, struct pdflush_work, list);  //从pdflush链表中取出一项list_del_init(&pdf->list);if (list_empty(&pdflush_list))last_empty_jifs = jiffies;pdf->fn = fn;pdf->arg0 = arg0;       //初始化具体的刷洗函数和参数,唤醒线程池进行刷洗wake_up_process(pdf->who);spin_unlock_irqrestore(&pdflush_lock, flags);}return ret;}




0 0
原创粉丝点击