pthread是什么

在需要多任务的编程中,多数情况下都是使用的pthread,网上查找资料的话,也有很多使用fork/vfork的例子。

pthread是线程,fork是进程,这是没有疑问的。

但是有资料又说,linux不区分进程和线程,或者说根本就没有实现线程。

可但是又有资料明明写着,有linux有内核线程。。。,查看内核代码确有kernel_thread,

真是傻傻分不清楚。

那么,下面就试着理一理头绪,不一定正确,只代表了当前的认识。

1.kernel_thread

内核源码:

init/main.c

asmlinkage void __init start_kernel(void)-->

static noinline void __init_refok rest_init(void){

 kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);

 pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);

cpu_idle();

}

rest_init中启动了两个内核线程kernel_init和kthreadd,

rest_init本身也是一个内核线程,最后死在cpu_idle中。

此后还会有很多地方

(待续。。。。。。)

在内核启动过程中会有很多地方通过kernel_thread创建内核线程(只是创建方法不像kernel_init和kthreadd这样显示调用)

大部分启动完成,干完自己的活就退出了。

这里rest_init本身是线程0, pid为0; kernel_init的pid为1,kthreadd的pid为2.

kernel_init最后会调用/sbin/init程序,成为第一个用户进程。

(待续。。。。。)

看一下kernel_thread的源码

/*

 * Create a kernel thread.

 */

pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)

{

 struct pt_regs regs;

 memset(®s, 0, sizeof(regs));


 regs.ARM_r4 = (unsigned long)arg;

 regs.ARM_r5 = (unsigned long)fn;

 regs.ARM_r6 = (unsigned long)kernel_thread_exit;

 regs.ARM_r7 = SVC_MODE | PSR_ENDSTATE | PSR_ISETSTATE;

 regs.ARM_pc = (unsigned long)kernel_thread_helper;

 regs.ARM_cpsr = regs.ARM_r7 | PSR_I_BIT;


 return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);

}

EXPORT_SYMBOL(kernel_thread);

也就是kernel_thread是通过do_fork实现的,当用户程序通过fork创建进程的时候,内核同样会进入到do_fork.

因此这就证明了,linux内核不区分线程和进程,他们是同一个东西,内核线程,也可以叫内核进程。

(待续。。。。)

kernel_init和kthreadd可以说是纯手工打造的,在内核启动的时候会创建很多内核线程,我们在写一个设备驱动的时候也可能需要创建一个线程

而这些地发不能用这种手工的方式,而是有更加通用的API。我们看一下kthreadd都做了什么

int kthreadd(void *unused)
{
 struct task_struct *tsk = current;
 /* Setup a clean context for our children to inherit. */
 set_task_comm(tsk, "kthreadd");
 printk("[%s-%d][%s] current->pid=%d,current->tgid=%d current->state=%d current->comm=%s\n",__FILE__,__LINE__,__func__,current->pid,current->tgid,current->state,current->comm);
 ignore_signals(tsk);
 set_cpus_allowed_ptr(tsk, cpu_all_mask);
 set_mems_allowed(node_states[N_HIGH_MEMORY]);
 current->flags |= PF_NOFREEZE | PF_FREEZER_NOSIG;
 printk("[%s-%d][%s] current->pid=%d,current->tgid=%d current->state=%d\n",__FILE__,__LINE__,__func__,current->pid,current->tgid,current->state);
 for (;;) {
 printk("[%s-%d][%s] current->pid=%d,current->tgid=%d current->state=%d\n",__FILE__,__LINE__,__func__,current->pid,current->tgid,current->state);
  set_current_state(TASK_INTERRUPTIBLE);
  if (list_empty(&kthread_create_list)){
 printk("[%s-%d][%s] call schedule\n",__FILE__,__LINE__,__func__);
   schedule();
  }
  __set_current_state(TASK_RUNNING);
  spin_lock(&kthread_create_lock);
  while (!list_empty(&kthread_create_list)) {   //检查list是否为空
   struct kthread_create_info *create;
   create = list_entry(kthread_create_list.next,   //获取一个create请求
         struct kthread_create_info, list);
   list_del_init(&create->list);
   spin_unlock(&kthread_create_lock);
   printk("[%s-%d][%s] create->threadfn=0x%x\n",__FILE__,__LINE__,__func__,create->threadfn);
   create_kthread(create);     //创建内核线程
   spin_lock(&kthread_create_lock);
  }
  spin_unlock(&kthread_create_lock);
 }
 return 0;
}



可以看到kthreadd就是查看kthread_create_list 如果不为空,则从列表取出一个create(请求),然后执行create_kthread(create);

去创建一个内核线程,可以想到一定有一个地发将这个create请求放到kthread_create_list上,它就是一个通用的创建内核线程的API,如下

struct task_struct *kthread_create(int (*threadfn)(void *data),
       void *data,
       const char namefmt[],
       ...)
{
 struct kthread_create_info create;

 create.threadfn = threadfn;
 create.data = data;
 init_completion(&create.done);

 spin_lock(&kthread_create_lock);
 list_add_tail(&create.list, &kthread_create_list);
 spin_unlock(&kthread_create_lock);

 wake_up_process(kthreadd_task);
 wait_for_completion(&create.done);

 if (!IS_ERR(create.result)) {
  struct sched_param param = { .sched_priority = 0 };
  va_list args;

  va_start(args, namefmt);
  vsnprintf(create.result->comm, sizeof(create.result->comm),
     namefmt, args);
  va_end(args);
  /*
   * root may have changed our (kthreadd's) priority or CPU mask.
   * The kernel thread should not inherit these properties.
   */
  sched_setscheduler_nocheck(create.result, SCHED_NORMAL, ¶m);
  set_cpus_allowed_ptr(create.result, cpu_all_mask);
 }
 return create.result;
}
EXPORT_SYMBOL(kthread_create);







你可能感兴趣的:(技术-linux)