Linux complete的使用记录

之前使用complete的时候,程序总是wait_for_completion函数先执行,并且每次只有一个wait_for_completion在等待,因此对于complete函数也没有太多的深入了解。后面再次需要使用这个功能的时候,想到如果wait_for_completion函数在complete之后执行会出现上面问题?

结论:如果wait_for_completion函数在complete之后执行,那么执行wait_for_completion函数时,添加就直接满足,不会再等待complete函数的执行。之所以是这样,是因为它实现的机制如下:

complete实现的函数如下:

void complete(struct completion *x)
{
	unsigned long flags;

	spin_lock_irqsave(&x->wait.lock, flags);
	x->done++;            //这个变量很重要
	__wake_up_locked(&x->wait, TASK_NORMAL, 1);
	spin_unlock_irqrestore(&x->wait.lock, flags);
}

wait_for_completion实现如下:

void __sched wait_for_completion(struct completion *x)
{
	wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE);
}
EXPORT_SYMBOL(wait_for_completion);

static long __sched
wait_for_common(struct completion *x, long timeout, int state)
{
	return __wait_for_common(x, schedule_timeout, timeout, state);
}

static inline long __sched
__wait_for_common(struct completion *x,
		  long (*action)(long), long timeout, int state)
{
	might_sleep();

	spin_lock_irq(&x->wait.lock);
	timeout = do_wait_for_common(x, action, timeout, state);
	spin_unlock_irq(&x->wait.lock);
	return timeout;
}

static inline long __sched
do_wait_for_common(struct completion *x,
		   long (*action)(long), long timeout, int state)
{
	if (!x->done) {
		DECLARE_WAITQUEUE(wait, current);

		__add_wait_queue_tail_exclusive(&x->wait, &wait);
		do {
			if (signal_pending_state(state, current)) {
				timeout = -ERESTARTSYS;
				break;
			}
			__set_current_state(state);
			spin_unlock_irq(&x->wait.lock);
			timeout = action(timeout);
			spin_lock_irq(&x->wait.lock);
		} while (!x->done && timeout);
		__remove_wait_queue(&x->wait, &wait);
		if (!x->done)
			return timeout;
	}
	x->done--;            //complete函数里面自加的变量
	return timeout ?: 1;
}

通过查看其实现的方式,发现complete实现的原理是:

struct completion {
    unsigned int done;
    wait_queue_head_t wait;
};

通过判断done的值,来判断complete是否执行,执行了多少次。

complete函数执行一次,done就加1

wait_for_completion函数执行一次,done就减1

如果done等于0,那么wait_for_completion函数将一直等待下去。

 

下面附上complete的简单实用:

struct completion temp_completion;    //定义一个变量
init_completion(&temp_completion);    //初始化变量

complete(&temp_completion);            //发送完成量    唤醒一个等待
wait_for_completion(&temp_completion);    //等待完成量


complete_all(&temp_completion);    //唤醒所有等待
wait_for_completion_timeout(&temp_completion, HZ);    //等待可以超时
wait_for_completion_interruptible(&temp_completion);    //等待可以被中断
wait_for_completion_interruptible_timeout(&temp_completion);    //等待可以超时、被中断

 

 

 

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

monkey_llll

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

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

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

打赏作者

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

抵扣说明:

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

余额充值