博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
pthread是什么
阅读量:4071 次
发布时间:2019-05-25

本文共 4190 字,大约阅读时间需要 13 分钟。

在需要多任务的编程中,多数情况下都是使用的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(&regs, 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, &regs, 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);

转载地址:http://prqji.baihongyu.com/

你可能感兴趣的文章
do_generic_file_read()函数
查看>>
Python学习笔记之数据类型
查看>>
Python学习笔记之特点
查看>>
Python学习笔记之安装
查看>>
shell 快捷键
查看>>
VIM滚屏操作
查看>>
EMC 2014存储布局及十大新技术要点
查看>>
linux内核内存管理(zone_dma zone_normal zone_highmem)
查看>>
将file文件内容转成字符串
查看>>
循环队列---数据结构和算法
查看>>
优先级队列-数据结构和算法
查看>>
链接点--数据结构和算法
查看>>
servlet中请求转发(forword)与重定向(sendredirect)的区别
查看>>
Spring4的IoC和DI的区别
查看>>
springcloud 的eureka服务注册demo
查看>>
eureka-client.properties文件配置
查看>>
MODULE_DEVICE_TABLE的理解
查看>>
platform_device与platform_driver
查看>>
platform_driver平台驱动注册和注销过程(下)
查看>>
.net强制退出主窗口的方法——Application.Exit()方法和Environment.Exit(0)方法
查看>>