主题:一些问题

时间:2010-09-20 17:51:45

标签: linux linux-kernel

我对线程有几个问题。能否澄清一下。

  1. 假设有一个或多个线程的进程。如果进程被抢占/暂停,线程是否也被抢占或者线程是否继续运行?

  2. 当重新安排暂停的进程时,进程线程是否也会被调度?如果进程有进程有多个线程,哪些线程将被重新安排,以什么为基础?

  3. 如果进程中的线程正在运行并收到一个信号(比如Cntrl-C)并且信号的默认动作是终止进程,正在运行的线程是终止还是父进程也会终止?如果由于某些信号而正在运行的进程终止,那么线程会发生什么?

  4. 如果线程执行fork fallowed exec,exece'd程序是否覆盖父进程或正在运行的线程的地址空间?如果它覆盖了父进程,那么线程,它们的数据,它们持有的锁以及exec'd进程终止后它们的调度方式会发生什么。

  5. 假设进程有多个线程,线程是如何调度的。如果其中一个线程阻塞某些I / O,则如何调度其他线程。与父进程一起安排的线程是否正在运行?

  6. 当线程正在运行当前内核变量指向的内容(父进程task_stuct或线程stack_struct?

  7. 如果线程的进程正在运行,则线程启动时进行父进程 进程被抢占以及每个线程如何安排?

  8. 如果在CPU上运行的进程创建多个线程,那么父进程创建的线程是否在多处理器系统上的另一个CPU上调度?

  9. 谢谢, 内甚

4 个答案:

答案 0 :(得分:5)

首先,我应该清楚一些您似乎对此感到困惑的术语。在POSIX中,“进程”是单个地址空间加上至少一个控制线程,由进程ID(PID)标识。线程是进程中单独调度的执行上下文。

所有进程都只使用一个线程启动,所有进程都在至少一个线程。现在,问题:

  
      
  1. 假设有一个或多个线程的进程。如果进程被抢占/暂停,线程是否也被抢占或者线程是否继续运行?
  2.   

线程是独立安排的。如果线程阻塞了connect()之类的函数,那么仍然可以调度进程中的其他线程。

也可以请求暂停进程中的每个线程,例如通过向进程发送SIGSTOP

  
      
  1. 当重新安排暂停的进程时,进程线程是否也会被调度?如果进程有进程有多个线程,哪些线程将被重新安排,以什么为基础?
  2.   

只有在明确请求停止整个过程的情况下才有意义。如果您发送进程SIGCONT以重新启动进程,则可以运行未阻止的任何线程。如果可以运行的线程多于可用于运行它们的处理器,那么未指定哪个线程首先运行。

  
      
  1. 如果进程中的线程正在运行并收到一个信号(例如Cntrl-C)并且信号的默认操作是终止进程,则正在运行的线程是终止还是父进程也会终止?如果由于某些信号而正在运行的进程终止,那么线程会发生什么?
  2.   

如果某个帖子收到了SIGINTSIGSEGV之类的信号,其动作是终止进程,那么整个过程就会终止。这意味着进程中的每个线程都被毫不客气地杀死。

  
      
  1. 如果线程执行fork后跟exec,exece'd程序是否覆盖父进程或正在运行的线程的地址空间?如果它覆盖了父进程,线程,它们的数据,它们持有的锁以及exec'd进程终止后它们的调度方式会发生什么。
  2.   

fork()调用通过复制原始进程的地址空间来创建新进程,并仅复制在该新地址空间中调用fork()的单个线程。

如果新进程中的该线程调用execve(),它将用exec'd程序替换新的重复地址空间。原始进程及其所有线程继续正常运行。

  
      
  1. 假设进程有多个线程,线程是如何进行调度的。如果其中一个线程阻塞某些I / O,则如何调度其他线程。使用父进程调度的线程是否正在运行?
  2.   

线程是独立安排的。任何未阻止的线程都可以运行。

  
      
  1. 当线程正在运行时当前内核变量指向什么(父进程task_stuct或线程stack_struct?
  2.   

每个线程在内核中都有自己的task_struct。用户空间称为“线程”的内容在内核空间中称为“进程”。因此current始终指向与当前正在执行的线程相对应的task_struct(在用户空间意义上的单词)。

  
      
  1. 如果正在运行[第二个]线程的进程,那么当线程启动时,父进程会被抢占以及每个线程的调度方式如何?
  2.   

大概你的意思是“流程的主线程”,而不是“父流程”。和以前一样,线程是独立调度的。未指定是否在另一个之前运行 - 如果您有多个CPU,则两者可能同时运行。

  
      
  1. 如果在CPU上运行的进程创建多个线程,那么父进程创建的线程是否在多处理器系统上的另一个CPU上调度?
  2.   

这完全取决于内核,但线程肯定是允许在其他CPU上执行。

答案 1 :(得分:1)

  1. 取决于。如果某个线程被抢占,因为OS调度程序决定给其他某个线程提供CPU时间,那么该进程中的其他线程将继续运行。如果进程被暂停(即它获得SIGSTP信号),那么AFAIK将暂停所有线程。

  2. 当挂起的进程被唤醒时,所有线程都被标记为等待或阻塞(如果它们正在等待,例如在互斥锁上)。然后某些点的调度程序运行它们。在唤醒进程后,无法保证线程的任何特定顺序。

  3. 该过程将终止,同时也会终止线程。

  4. 当您分叉时,您会获得一个新的地址空间,因此没有“叠加”。请注意,fork()和exec()系列会影响整个进程,而不仅仅是调用它们的线程。当您在多线程进程中调用fork()时,子进程会获得该进程的副本,但只有调用线程。然后,如果你在一个或两个进程中调用exec()(可能只在子进程中,但这取决于你),那么调用exec()(及其所有线程)的进程将被替换为exec()'ed program。

  5. 线程调度顺序由OS调度程序决定,不保证给出任何特定的顺序。

  6. 从内核的角度来看,进程是一个包含一个或多个线程(以及其他一些gunk)的地址空间。没有进程就没有线程概念存在。

  7. 没有单个线程就没有进程这样的东西。 “普通流程”只是一个单线程的流程。

  8. 可能是的。这由OS调度程序确定。请注意,有一些API和工具(numactl)可以用来强制某些线程在特定的CPU核心上运行。

答案 2 :(得分:0)

假设您的问题与POSIX线程有关,那么

1a上。由操作系统抢占的进程将抢占其所有线程。

1b中。 O / S将挂起发送SIGSTOP的进程的所有线程。

  1. O / S将恢复发送SIGCONT的暂停进程的所有线程。

  2. 默认情况下,SIGINT将终止进程中的所有线程。

  3. 如果一个线程调用fork(),那么它的所有线程都是重复的。如果它然后调用其中一个exec()函数,那么所有重复的线程都会消失。

  4. POSIX允许用户选择线程调度算法。

  5. 我不明白这个问题。

  6. 我不明白这个问题。

  7. 线程如何映射到CPU-s是依赖于实现的。许多实现都会尝试在可用的CPU之间分配线程以提高性能。

答案 3 :(得分:0)

Linux内核不区分线程和进程。就内核而言,线程只是另一个与其他进程共享地址空间的进程。 (您可以将共享单个地址空间的“进程”(即线程)称为“进程”。)

所以POSIX线程的安排与完全成熟的进程完全相同。调度是否有一个进程有五个线程或五个独立进程没有区别。

有内核调用可以对进程之间共享的内容进行细粒度控制。 POSIX线程API包装它们。