区别和联系 我们经常提到线程、线程组、内核进程、用户进程、轻量级进程等词汇,那么他们之间有什么区别和联系呢? 首先,我们需要明确一点,Linux下并没有真正意义上的线程,甚至可以说没有进程这个概念,Linux下只有task,其对应的数据结构为task_struct,这里为了方便说明以及按照比较主流的说法,我们将task称之为进程。 对于一个进程来说,它一定是运行在内存的某个连续或不连续的区域,先以用户进程为例。 用户进程和内核进程 对于Linux来说,有两个概念叫做内核空间和用户空间,以32位x86架构的Linux为例,Linux的虚拟地址空间为4GB,其中前1GB称为内核空间,后3GB称为用户空间,进程运行在内核空间时称为内核态,运行在用户空间称之为用户态。对于用户态进程来说,出于程序设计方便和内存安全的角度等原因,为每个用户态进程引入了独立的虚拟地址空间,其被映射到用户空间。 用户进程,平时运行在用户态,有自己的虚拟地址空间,但是可以通过中断、系统调用等内陷到内核态。 内核进程,没有独立的地址空间,所有内核线程的地址空间都是一样的,没有自己的地址空间,所以它们的”current->mm”都为空,其运行在内核空间,本身就是内核的一部分或者说是内核的分身。 线程、轻量级进程、线程组和用户进程 我们开始说到,linux下没有真正意义上的线程,那么linux下的线程是什么呢? 我们说过Linux下只有task,对应的数据结构为task_struct,task_strcut中就包含了task所拥有的各种资源,如果一个运行在用户空间的task独占task_struct的所有资源,我们说它是一个用户进程,当若干个task要共享资源时,我们把这些task称之为LWP(轻量级线程)。 Linux的线程只是共享了资源的进程,所以在Linux下,线程其实就是LWP,而那些共享了资源的task组合在一起,我们称之为线程组。 即对于普通的用户进程,我们可以认为是只有一个LWP的线程组,但对于一个有着多线程的进程(线程组),其中的每一个线程都是LWP,组内共享资源。在一个普通进程内创建线程时,就是在线程组内增加LWP。 进程的创建 在Linux下,有着这几个创建进程(task)的函数: fork vfork clone pthread_create kernel_thread 所有的这些函数,最终都是在调用do_fork(),只是传入的参数不同 fork(sys_fork)在调用do_fork()时,clone_flags没有置位任何clone标志位,即创建的进程不共享任何数据。 vfork(sys_vfork)在调用do_fork()时,置为了CLONE_VFORK CLONE_VM,即共享VM,以及当mm_release时子进程唤醒父进程 clone(sys_clone)本身只进行clone_flags的传递 pthread_create 则将CLONE_VM CLONE_FS CLONE_FILES CLONE_SIGHAND等标志位置位,即共享VM,共享fs info,共享打开的文件,共享信号句柄和阻塞的信号? 即除了栈是独立的,其他都是共享的,所以在linux中,线程仅仅是一个使用共享资源的轻量级进程 kernel_thread 在传递的参数基础上增加了CLONE_VM和CLONE_UNTRACED。 kernel_thread 只能由内核进程调用,创建的进程没有独立虚拟地址空间,只能运行在内核空间,为内核进程。 fork,创建的进程与父进程不共享资源,而是写时复制,故而创建的是用户进程 vfork,带有CLONE_VM标志位,故而创建的是LWP pthread_create,共享各类资源,创建的也是LWP 关于fork vfork clone pthread_create kernel_thread 以及 do_fork更进一步的细节,先挖个坑,以后再填 (责任编辑:IT) |