这里可能会询问 4 种不同类型的线程。
- 内核自己创建的用于处理后台任务的线程。
fork()
系统调用派生的进程。
- pthread 线程由用户使用 Linux
clone()
系统调用创建但由内核管理
- 完全在内核调度程序之外运行的“绿色”线程
以下答案假设帖子中提到的“用户级”线程是 pthread 品种,而不是“绿色”品种。
编辑:我认为@Hristo 是对的,OP 正在谈论“绿色”线程或者混淆了两者。
此答案假定您正在谈论您使用创建的线程pthread_create()
。还有一些“绿色”线程由用户空间调度,内核不知道。我将把我的答案留给后代。
用户线程 == 绿色线程
所谓的“绿色线程”根据定义是完全由 VM 处理而无需内核参与的线程。
“用户级”内核对线程一无所知,因此该进程一次最多使用一个处理器/内核。
对。
如果一个线程进行阻塞调用,所有线程将再次被阻塞,因为内核不知道线程的存在
不会。只要您使用正确的原语,阻塞调用将导致线程被放入等待队列并运行另一个绿色线程。
创建内核级线程时,进程的 .text(code area) 如何修改?
在绿色线程中,它们都使用相同的代码区域。
此外,所有其他区域将保持不变(.bss、堆等)。
是的。
用户线程 == pthreads
对于pthread_create()
“用户线程”,它们与“内核”线程之间几乎没有区别。clone()
linux内核使用系统调用 将用户级线程实现为单独的内核进程。clone()
创建一个使用与父进程相同的内存空间的新进程,而不是fork()
创建一个具有父内存副本的新进程。
“用户级”内核对线程一无所知,因此该进程一次最多使用一个处理器/内核。
不,这是不正确的。内核像任何其他进程一样管理用户级线程,因为它具有上下文切换和在多个 CPU 上调度各种用户级线程的能力等。
如果一个线程进行阻塞调用,所有线程将再次被阻塞,因为内核不知道线程的存在
不,一个线程可以阻塞,而其他线程将继续运行。同样,这是在 pthread 样式线程下。
创建内核级线程时,进程的 .text(code area) 如何修改?
创建新线程时,它会继承其父线程的内存分段表。文本/代码页(和其他只读页)被标记为只读,并且两个线程在线程的生命周期内共享内存。所有读写页面也是共享的,直到新线程对这些部分进行写入,此时页面被复制到另一个位置(写入时复制)。
此外,所有其他区域将保持不变(.bss、堆等)。
不,堆页面以及其他未标记为只读的内容(包括您提到的堆栈)将在写入后立即被复制。我不确定 .bss 部分,但由于它们是在运行时初始化的,我相信它们也是读写的。DATA 是只读的。