Chinaunix首页 | 论坛 | 博客
  • 博客访问: 208366
  • 博文数量: 65
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 91
  • 用 户 组: 普通用户
  • 注册时间: 2015-04-10 09:41
文章分类
文章存档

2020年(1)

2018年(1)

2017年(30)

2016年(30)

2015年(3)

我的朋友

分类: LINUX

2017-07-10 10:21:58

原文地址:内核线程 作者:add358

 在linux内核中,所谓的内核线程实际上是一个共享父进程地址空间的进程,它有自己的系统堆栈;所以它们依然是一个进程,只不过这些进程可以与其他进程共享某些资源,这里的其他进程也是所谓的线程。

1 内核线程与普通进程的异同
 1.1 内核线程没有自己的地址空间,所以它们的"current->mm"都是空的;
 1.2 内核线程只能在内核空间操作,不能与用户空间交互;
 1.3 跟普通进程一样,内核线程也有优先级和被调度。

2 内核线程创建

 在内核中,有两种方法可以生成内核线程,一种是使用kernel_thread()接口,另一种是用kthread_create()接口。
 先说kernel_thread接口,使用该接口创建的线程,必须在该线程中调用daemonize()函数,这是因为只有当线程的父进程指向"Kthreadd"时,该线程才算是内核线程,而恰好daemonize()函数主要工作便是将该线程的父进程改成“kthreadd"内核线程;默认情况下,调用deamonize()后,会阻塞所有信号,如果想操作某个信号可以调用allow_signal()函数。
 而kthread_create接口,则是标准的内核线程创建接口,只须调用该接口便可创建内核线程;默认创建的线程是存于不可运行的状态,所以需要在父进程中通过调用wake_up_process()函数来启动该线程。

3 内核线程的退出
 当线程执行到函数末尾时会自动调用内核中do_exit()函数来退出或其他线程调用kthread_stop()来指定线程退出。

4 内核线程接口
 4.1 kernel_thread接口
  1. int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); 
  2.             // fn为线程函数,arg为线程函数参数,flags为标记
  3. void daemonize(const char * name,...); // name为内核线程的名称
   注:这里的flags的取值为

点击(此处)折叠或打开

  1. CSIGNAL       /* signal mask to be sent at exit */
  2. CLONE_VM      /* set if VM shared between processes */
  3. CLONE_FS      /* set if fs info shared between processes */
  4. CLONE_FILES   /* set if open files shared between processes */
  5. CLONE_SIGHAND /* set if signal handlers and blocked signals shared */
  6. CLONE_PTRACE  /* set if we want to let tracing continue on the child too */
  7. CLONE_VFORK   /* set if the parent wants the child to wake it up on mm_release */
  8. CLONE_PARENT  /* set if we want to have the same parent as the cloner */
  9. CLONE_THREAD  /* Same thread group? */
  10. CLONE_NEWNS   /* New namespace group? */
  11. CLONE_SYSVSEM /* share system V SEM_UNDO semantics */
  12. CLONE_SETTLS  /* create a new TLS for the child */
  13. CLONE_PARENT_SETTID   /* set the TID in the parent */
  14. CLONE_CHILD_CLEARTID  /* clear the TID in the child */
  15. CLONE_DETACHED        /* Unused, ignored */
  16. CLONE_UNTRACED        /* set if the tracing process can't force CLONE_PTRACE 
  17.                          on this clone */
  18. CLONE_CHILD_SETTID    /* set the TID in the child */
  19. CLONE_NEWUTS          /* New utsname group? */
  20. CLONE_NEWIPC          /* New ipcs */
  21. CLONE_NEWUSER         /* New user namespace */
  22. CLONE_NEWPID          /* New pid namespace */
  23. CLONE_NEWNET          /* New network namespace */
  24. CLONE_IO              /* Clone io context */

 4.2 kthread_create接口
  1. struct task_struct *kthread_create(int (*threadfn)(void *data),void *data,
  2.                                   const char namefmt[], ...);
  3.  //threadfn为线程函数;data为线程函数参数;namefmt为线程名称,可被格式化的
  4. int wake_up_process(struct task_struct *p); //唤醒线程
  5. struct task_struct *kthread_run(int (*threadfn)(void *data),void *data,
  6.                                 const char namefmt[], ...);//是以上两个函数的功能的总和
注:因为线程也是进程,所以其结构体也是使用进程的结构体"struct task_struct"。

5 示例代码    kthread.rar   

点击(此处)折叠或打开

  1. #include <linux/module.h>
  2. #include <linux/init.h>
  3. #include <linux/kernel.h>
  4. #include <linux/kthread.h>

  5. MODULE_LICENSE("Dual BSD/GPL");
  6. MODULE_AUTHOR("Kozo");

  7. static int noop(void *dummy)
  8. {
  9.     int i = 0;
  10.     daemonize("mythread");  /*使用kernel_thread创建的线程,需要调用该函数*/
  11.     while(i++ < 5)
  12.     {
  13.         printk("my thread:current->mm = %p\n",current->mm);
  14.         printk("my thread:current->active_mm = %p\n",current->active_mm);
  15.         set_current_state(TASK_INTERRUPTIBLE);
  16.         schedule_timeout(10*HZ);
  17.     }
  18.     return 0;
  19. }

  20. static int noop2(void *dummy)
  21. {
  22.     int i = 0;
  23.     while(i++ < 5)
  24.     {
  25.         printk("my thread:current->mm = %p\n",current->mm);
  26.         printk("my thread:current->active_mm = %p\n",current->active_mm);
  27.         set_current_state(TASK_INTERRUPTIBLE);
  28.         schedule_timeout(10*HZ);
  29.     }
  30.     return 0;
  31. }
  32. static __init int demo_init(void)
  33. {

  34.     printk(KERN_INFO"demo init\n");
  35.     printk("demo init:current->mm = %p\n",current->mm);
  36.     printk("demo init:current->active_mm = %p\n",current->active_mm);
  37.     //kernel_thread(noop, NULL, CLONE_KERNEL|SIGCHLD);
  38.     kthread_run(noop2,NULL,"mythread");
  39.     return 0;
  40. }

  41. static __exit void demo_exit(void)
  42. {
  43.     printk(KERN_INFO"demo exit\n");
  44. }

  45. module_init(demo_init);
  46. module_exit(demo_exit);
6 执行结果

从结果可以看出,子线程的地址空间是没有的。

转载请注明出处:add358.blog.chinaunix.net
阅读(1353) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~