exit()函数_complete函数

c74dc8d61a76f3b550d064e4428f16f1.png

上次讲解了一下add_wait_queue和add_wait_queue_exclusive两个函数,今天来讲另一个函数complete函数。

文件包含:

#include<linux/completion.h>

这个函数也是与内核进程调度相关的一个函数,因此它也位于kernel/sched/目录下,具体的实现在completion.c中,我们可以看看它的具体实现,这样对于我们更好的理解它的工作原理会很有帮助。

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);
}

我们可以看到,事实上complete函数调用了__wake_up_locked函数,只是在调用时采用了自旋锁并且关闭了中断。

函数功能:

complete函数用于唤醒等待队列中的睡眠进程,并记录等待队列中的唤醒次数,保存在字段done中。函数的参数是completion的一个结构体。

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

completion结构体除了done字段之外,就是一个wait_queue_head_t的等待队列头。需要注意的是能唤醒的进程状态只能是TASK_INTERRUPTIBLE或者TASK_UNINTERRUPTIBLE,并且唤醒进程不是同步的,就是说只能唤醒一个然后再去唤醒另一个。

实例解析:

#include<linux/init.h>
#include<linux/module.h>
#include<linux/sched.h>
#include<linux/wait.h>
#include<linux/completion.h>
#include<linux/kthread.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("viz.xu, xujiweigo@163.com");

static struct completion comple;
static struct task_struct* old_task;

int my_test_function(void* args)
{
	printk("enter kernel function!n");
	printk("the current pid is %dn",current->pid);
	printk("the value of done of the comple:%dn",comple.done);
	printk("the state of the init thread is %ldn",old_task->state);
	
	complete(&comple);

	printk("the value of done of the comple:%dn",comple.done);
	printk("the state of the init thread is %ldn",old_task->state);

return 0;
}

int __init complete_init(void)
{
	printk("complete init! current->pid = %dn",current->pid);

	struct task_struct* new_task = NULL;

	old_task = current;
	
	new_task = kthread_create_on_node(my_test_function,NULL,-1,"comple");

	init_completion(&comple);

	wait_queue_entry_t data;
	init_waitqueue_entry(&data,current);	

	wake_up_process(new_task);

	add_wait_queue(&(comple.wait),&data);
	
	long left_time = schedule_timeout_uninterruptible(1000);

	printk("the pid of new_task is %dn",new_task->pid);

	printk("the return result of the schedule_timeout_uninterruptible is %dn",left_time);

return 0;
}

void __exit complete_exit(void)
{
	printk("complete exit!n");
return;
}

module_init(complete_init);
module_exit(complete_exit);

结果分析:

[ 2814.212263] complete init! current->pid = 40020
[ 2814.212397] enter kernel function!
[ 2814.212399] the current pid is 40021
[ 2814.212400] the value of done of the comple:0
[ 2814.212401] the state of the init thread is 2
[ 2814.212403] the value of done of the comple:1
[ 2814.212404] the state of the init thread is 0
[ 2814.212406] the pid of new_task is 40021
[ 2814.212407] the return result of the schedule_timeout_uninterruptible is 1000

从结果可以看出,子进程和父进程都执行了,并且子进程在父进程之前执行完毕。在my_test_ function中调用complete函数,父进程的状态发生了改变2->0,这是因为我们在init函数中调用了schedule_timeout_uninterruptible,使得父进程处于TASK_UNINTERRUPTIBLE状态。同是,调用complete函数之后,comple的done字段变为1,说明参数在等待队列被唤醒了一次。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值