pdflush代码分析

前文对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
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数据存储张

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值