我对线程有几个问题。能否澄清一下。
假设有一个或多个线程的进程。如果进程被抢占/暂停,线程是否也被抢占或者线程是否继续运行?
当重新安排暂停的进程时,进程线程是否也会被调度?如果进程有进程有多个线程,哪些线程将被重新安排,以什么为基础?
如果进程中的线程正在运行并收到一个信号(比如Cntrl-C)并且信号的默认动作是终止进程,正在运行的线程是终止还是父进程也会终止?如果由于某些信号而正在运行的进程终止,那么线程会发生什么?
如果线程执行fork fallowed exec,exece'd程序是否覆盖父进程或正在运行的线程的地址空间?如果它覆盖了父进程,那么线程,它们的数据,它们持有的锁以及exec'd进程终止后它们的调度方式会发生什么。
假设进程有多个线程,线程是如何调度的。如果其中一个线程阻塞某些I / O,则如何调度其他线程。与父进程一起安排的线程是否正在运行?
当线程正在运行当前内核变量指向的内容(父进程task_stuct或线程stack_struct?
如果线程的进程正在运行,则线程启动时进行父进程 进程被抢占以及每个线程如何安排?
如果在CPU上运行的进程创建多个线程,那么父进程创建的线程是否在多处理器系统上的另一个CPU上调度?
谢谢, 内甚
答案 0 :(得分:5)
首先,我应该清楚一些您似乎对此感到困惑的术语。在POSIX中,“进程”是单个地址空间加上至少一个控制线程,由进程ID(PID)标识。线程是进程中单独调度的执行上下文。
所有进程都只使用一个线程启动,所有进程都在至少一个线程。现在,问题:
- 假设有一个或多个线程的进程。如果进程被抢占/暂停,线程是否也被抢占或者线程是否继续运行?
醇>
线程是独立安排的。如果线程阻塞了connect()
之类的函数,那么仍然可以调度进程中的其他线程。
也可以请求暂停进程中的每个线程,例如通过向进程发送SIGSTOP
。
- 当重新安排暂停的进程时,进程线程是否也会被调度?如果进程有进程有多个线程,哪些线程将被重新安排,以什么为基础?
醇>
只有在明确请求停止整个过程的情况下才有意义。如果您发送进程SIGCONT
以重新启动进程,则可以运行未阻止的任何线程。如果可以运行的线程多于可用于运行它们的处理器,那么未指定哪个线程首先运行。
- 如果进程中的线程正在运行并收到一个信号(例如Cntrl-C)并且信号的默认操作是终止进程,则正在运行的线程是终止还是父进程也会终止?如果由于某些信号而正在运行的进程终止,那么线程会发生什么?
醇>
如果某个帖子收到了SIGINT
或SIGSEGV
之类的信号,其动作是终止进程,那么整个过程就会终止。这意味着进程中的每个线程都被毫不客气地杀死。
- 如果线程执行fork后跟exec,exece'd程序是否覆盖父进程或正在运行的线程的地址空间?如果它覆盖了父进程,线程,它们的数据,它们持有的锁以及exec'd进程终止后它们的调度方式会发生什么。
醇>
fork()
调用通过复制原始进程的地址空间来创建新进程,并仅复制在该新地址空间中调用fork()
的单个线程。
如果新进程中的该线程调用execve()
,它将用exec'd程序替换新的重复地址空间。原始进程及其所有线程继续正常运行。
- 假设进程有多个线程,线程是如何进行调度的。如果其中一个线程阻塞某些I / O,则如何调度其他线程。使用父进程调度的线程是否正在运行?
醇>
线程是独立安排的。任何未阻止的线程都可以运行。
- 当线程正在运行时当前内核变量指向什么(父进程task_stuct或线程stack_struct?
醇>
每个线程在内核中都有自己的task_struct
。用户空间称为“线程”的内容在内核空间中称为“进程”。因此current
始终指向与当前正在执行的线程相对应的task_struct
(在用户空间意义上的单词)。
- 如果正在运行[第二个]线程的进程,那么当线程启动时,父进程会被抢占以及每个线程的调度方式如何?
醇>
大概你的意思是“流程的主线程”,而不是“父流程”。和以前一样,线程是独立调度的。未指定是否在另一个之前运行 - 如果您有多个CPU,则两者可能同时运行。
- 如果在CPU上运行的进程创建多个线程,那么父进程创建的线程是否在多处理器系统上的另一个CPU上调度?
醇>
这完全取决于内核,但线程肯定是允许在其他CPU上执行。
答案 1 :(得分:1)
取决于。如果某个线程被抢占,因为OS调度程序决定给其他某个线程提供CPU时间,那么该进程中的其他线程将继续运行。如果进程被暂停(即它获得SIGSTP信号),那么AFAIK将暂停所有线程。
当挂起的进程被唤醒时,所有线程都被标记为等待或阻塞(如果它们正在等待,例如在互斥锁上)。然后某些点的调度程序运行它们。在唤醒进程后,无法保证线程的任何特定顺序。
该过程将终止,同时也会终止线程。
当您分叉时,您会获得一个新的地址空间,因此没有“叠加”。请注意,fork()和exec()系列会影响整个进程,而不仅仅是调用它们的线程。当您在多线程进程中调用fork()时,子进程会获得该进程的副本,但只有调用线程。然后,如果你在一个或两个进程中调用exec()(可能只在子进程中,但这取决于你),那么调用exec()(及其所有线程)的进程将被替换为exec()'ed program。
线程调度顺序由OS调度程序决定,不保证给出任何特定的顺序。
从内核的角度来看,进程是一个包含一个或多个线程(以及其他一些gunk)的地址空间。没有进程就没有线程概念存在。
没有单个线程就没有进程这样的东西。 “普通流程”只是一个单线程的流程。
可能是的。这由OS调度程序确定。请注意,有一些API和工具(numactl)可以用来强制某些线程在特定的CPU核心上运行。
答案 2 :(得分:0)
假设您的问题与POSIX线程有关,那么
1a上。由操作系统抢占的进程将抢占其所有线程。
1b中。 O / S将挂起发送SIGSTOP的进程的所有线程。
O / S将恢复发送SIGCONT的暂停进程的所有线程。
默认情况下,SIGINT将终止进程中的所有线程。
如果一个线程调用fork(),那么它的所有线程都是重复的。如果它然后调用其中一个exec()函数,那么所有重复的线程都会消失。
POSIX允许用户选择线程调度算法。
我不明白这个问题。
我不明白这个问题。
线程如何映射到CPU-s是依赖于实现的。许多实现都会尝试在可用的CPU之间分配线程以提高性能。
答案 3 :(得分:0)
Linux内核不区分线程和进程。就内核而言,线程只是另一个与其他进程共享地址空间的进程。 (您可以将共享单个地址空间的“进程”(即线程)称为“进程”。)
所以POSIX线程的安排与完全成熟的进程完全相同。调度是否有一个进程有五个线程或五个独立进程没有区别。
有内核调用可以对进程之间共享的内容进行细粒度控制。 POSIX线程API包装它们。