上次讲解了一下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,说明参数在等待队列被唤醒了一次。

exit()函数_complete函数相关推荐

  1. exit()和_exit()函数

    进程就好比人一样有其生命,我们通过fork()函数来创建一个进程,那么我们又是如何来中止进程呢. 进程退出 1.在Linux中任何让一个进程退出 进程退出表示进程即将结束.在Linux中进程退出分为了 ...

  2. exit()函数学习

    1.exit()函数介绍 函数名: exit() 所在头文件:stdlib.h 功 能: 关闭所有文件,终止正在执行的进程. 用法格式:void exit(int status) exit() 是电脑 ...

  3. Linux下Exit和_exit函数说明

    exit和_exit函数都是用来终止进程的.当程序执行到exit或_exit时,系统无条件的停止剩下所有操作,清除包括PCB(进程控制块)在内的各种数据结构,并终止本进程的运行.但是,这两个函数是有区 ...

  4. 浅析exit()和atexit()函数

    当内核使用一个一个exec函数执行c程序时,在调用main函数之前先调用一个特殊的启动例程,可执行程序需将此例程指定为程序的起始地址.启动例程从内核获取命令行参数和环境变量,然后为调用mian函数做好 ...

  5. C/C++中的exit()函数

    C/C++中的exit()函数参数 exit()函数本身表示退出程序. 其中: exit(0):表示正常退出 exit(1):表示出错(或非正常)退出.当然,exit()的参数可以不只是1,也可以是其 ...

  6. exit和_exit函数

    1.exit函数 1 #include <stdlib.h> 2 void exit(int status); 3 功能:退出当前进程 4 参数: 5 status:退出状态,由父进程通过 ...

  7. C语言通用工具库之exit()和atexit()函数

    一.exit()和atexit()函数 exit()退出程序.在main()函数返回系统时将自动调用exit()函数. atexit()函数通过退出时注册被调用的函数提供这种功能,atexit()接受 ...

  8. c语言中exit函数_C ++中的exit()函数

    c语言中exit函数 介绍 (Introduction) Today we'll learn about exit() in C++. We know we can break out of loop ...

  9. Linux多任务编程之五:exit()和_exit()函数(转)

    来源:CSDN  作者:王文松   转自:Linux公社 ----------------------------------------------------------------------- ...

最新文章

  1. 防止在iOS设备中的Safari将数字识别为电话号码
  2. vue引用公用的头部和尾部文件。
  3. 采购订单模板_采购必备:如何搭建合规的采购流程
  4. mysql+nginx实现负载均衡
  5. java listen_java web-- listen
  6. (JSP)关于手机端(尤其是苹果手机)pdf文件无法打开的解决方案
  7. 知识管理在中国的发展趋势
  8. 计算机word制作成绩单,如何用word批量制作学生成绩单?
  9. java编译网络爬虫_自己动手做网络爬虫系列——1 | 学步园
  10. 虚拟机xp系统如何安装--win10专业版
  11. 我的世界java版和基岩版对比_我的世界:java版和基岩版你更看好哪个?未来的发展,谁会更好...
  12. 关于Touch的顺时针(CW),逆时针(CCW)旋转
  13. 关于order by的一些用法
  14. matlab软件及基础实验第8单元,《MATLAB统计分析与应用:40个案例分析》程序与数据(内含彩蛋)...
  15. Spring Boot + Spring Security + JWT + 微信小程序登录
  16. 三角形加几笔能变成什么_一个圆添上几笔能出来什么形状?例如:表,太阳,向日葵.-圆形加几笔得什么事物-数学-伍靖都同学...
  17. 运营商大数据的范围有多广
  18. android fake gps,Fake GPS Location
  19. 为什么现在深度学习才流行起来?
  20. SolidWorks toolbox齿轮再修改方法

热门文章

  1. 金融时间序列计算分析题1
  2. 网页html转为pdf,html页面转换成PDF文件
  3. 编程大神进阶,Python技巧小贴士
  4. 5个Python特性 越早知道越好的
  5. PyCharm中Scrapy的安装
  6. 如何得到发送邮件服务器地址(SMTP地址)
  7. LinQ To Object 基本用法
  8. C#开发ActiveX控件及制作CAB包
  9. “ORA-01034 - Oracle not available”和“ORA-27101 - shared memory realm does not exist”
  10. torch tensor去掉1维_浑身是刺的“维c之王”,有人管它叫“菠萝”,有人管它叫“梨”...