linux中process, kernel thread, user thread的区别

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yyf_it/article/details/52421496

进程的contex switch开销较大:因为需要change 地址空间,但change address space is simply a register change in the CPU?改变页表寄存器中的地址即可啊,为什么开销大呢,其实是因为需要"flusing the translation look-aside buffer"

线程间的contex switch开销较小:但是会有cache miss的问题

Thread models: between kernel and user threads, a process might use one of three models: (1:1); (M:1)一个kernel threads 多个user thread; (M:M)多个kernel threads 和多个user threads.

Linux中使用一对一的方式,一个user thread 对应一个kernel thread


Linux的线程实现是在核外进行的,核内提供的是创建进程的接口do_fork()。内核提供了两个系统调用__clone()和fork(),最终都用不同的参数调用do_fork()核内API。 do_fork() 提供了很多参数,包括CLONE_VM(共享内存空间)、CLONE_FS(共享文件系统信息)、CLONE_FILES(共享文件描述符表)、CLONE_SIGHAND(共享信号句柄表)和CLONE_PID(共享进程ID,仅对核内进程,即0号进程有效)。当使用fork系统调用产生多进程时,内核调用do_fork()不使用任何共享属性,进程拥有独立的运行环境。当使用pthread_create()来创建线程时,则最终设置了所有这些属性来调用__clone(),而这些参数又全部传给核内的do_fork(),从而创建的”进程”拥有共享的运行环境,只有栈是独立的,由 __clone()传入

clone(), fork(), vfork()

Linux中,轻量级进程是由名为clone()的函数创建的,实际上clone()是C语言库中定义的一个封装。它负责创建新轻量级进程的栈并且调用对编程者隐藏的clone()系统调用。fork()最后也是调用clone(), vfork()。

do_fork函数负责处理clone(), fork(), 和vfork()系统调用

有些系统进程只运行在内核态,所有现代操作系统把它们的函数委托给内核线程,内核线程不受不必要的用户态上下文的拖累

内核线程与普通线程的区别

  • 内核线程只运行在内核态,而普通进程既可以运行在内核态,也可以运行在用户态
  • 因为内核线程只运行在内核态,它们只使用线性地址的高地址,普通进程可以使用4GB的线性地址空间

1.进程和线程的异同

 如上所述,linux中进程和线程的创建最终都会调用do_fork()进行创建,linux中进程的调度也不区分进程和线程。

区别在于

  • 进程是资源分配管理的最小单位,线程是调度的最小单位
  • 进程有自己独立的地址空间,多个线程需要共享进程的地址空间,除了:程序计数器,stack和寄存器是私有的。
  • 进程的优缺点对比

为了充分利用多核资源,常使用多进程和多线程的方式,进行并行编程,使用多进程存在的问题是

  • fork一个子进程的消耗是很大的,fork是一个昂贵的系统调用。
  • 进程的调度,进程的上下文切换需要切换很多资源,比如pagetable,开销大
  • 各个进程拥有自己独立的地址空间,进程间的协作需要复杂的IPC技术,如消息传递和共享内存等,不利于共享。

使用线程的优点:

便于线程间的共享和通信

缺点在于:

由于各线程共享进程的地址空间,因此可能会导致竞争,因此对某一块有多个线程要访问的数据需要一些同步技术




猜你喜欢

转载自blog.csdn.net/yyf_it/article/details/52421496