现代操作系统使用分时技术管理多个运行程序,对用户来说似乎是同步执行的。当然,如果机器上有多个CPU,会有多个程序真正同步运行。但是为了简单起见,我们假设只有一个处理器,在这种情况下同步只是一种表面现象。
操作系统将运行程序的每个实例表述为进程(Unix术语)或任务(Windows术语)。因此,同时执行的单个程序的多个调用(例如vi文本编辑器的同步会话)是各自独立的进程。在只有一个CPU的机器上,进程必须“轮换”操作。为了形象地说明,让我们假定每个“周期”(称为时间片)的长度为30毫秒。
当一个进程运行了30毫秒以后,硬件计时器发出一个中断,导致操作系统运行。我们假定这个进程被别的进程抢占了时间片。操作系统保存被中断进程的当前状态,因此以后可以恢复其状态,然后选择可以得到时间片的下一个进程。这个过程称为环境切换,因为CPU的执行环境从一个进程切换到另一个进程。这个循环无限重复。
轮换状态可能提前终结。例如,当进程需要执行输入/输出时,最终会调用操作系统中的一个执行低层硬件操作的函数,比如说调用C库函数scanf()会导致进行Unix OS read()系统调用,他需要与键盘驱动程序进行交互。这样,进程将它的轮换安排让给操作系统,提前结束了轮换状态。
这种情况说明了一个问题,给定进程时间片的调度是相当随机的。用户思考然后按下一个键所花的时间也是随机的,因此无法预测下次时间片何时开始。而且,如果调试的是多线程程序,则不知道将要调度的线程次序,这会使调试更加困难。
更细致地看:操作系统中有一个进程表,列出了关于当前所有进程的信息。一般来说,每个进程在进程表中被标记为Run状态或Sleep状态。让我们来看一个示例,其中一个运行程序到达需要从键盘读取输入的位置。正如刚刚提到的,这种情况会结束进程的轮换状态。因为进程现在在等待I/O完成,所以操作系统将其标记为处于Sleep状态,使它无资格占用时间片。因此,在Sleep状态意味着进程被阻塞,等待某个事件的发生。当这个事件最终发生后,操作系统会将它在进程表中的状态改回到Run。
非I/O事件也可以触发进程变成Sleep状态。例如,如果一个父进程创建了一个子进程,并调用wait(),那么父进程会阻塞,直到子进程完成它的工作并且结束。同样,这件事发成的确切时间是无法预测的。
而且,在Run状态中并不表示进程实际在CPU上执行;相反,这仅意味着它准备运行,即有资格得到CPU的时间片。一旦发生了环境切换,操作系统就根据进程表从当前处于Run状态的进程中选择一个进程占用CPU的一个周期。操作系统使用这个调度过程来选择新的环境,保证任何给定进程都能获得时间片,因而最终会完成,但是不承诺它会收到哪些时间片。因此,等待的事件发生后,Sleep进程真正“醒来“的确切时间是随机的,进程完成的准确速率也是随机的。
线程与进程非常类似,只是线程占用的内存比进程少,创建线程和在两个线程之间切换所需的时间较少。事实上,线程有时被称为“轻量级“进程,根据线程系统和运行时环境,它们甚至可能被作为操作系统的进程实现。像使用进程完成工作的程序一样,多线程应用程序一般会执行一个main()进程,该过程创建一个或多个子线程。父线程main()也是线程。
进程和线程之间的主要区别是:与进程一样,虽然每个线程有自己的局部变量,但是多线程环境中父程序的全局变量被所有线程共享,并作为在线程之间通信的主要方法。(虽然也可以在Unix进程之间共享全局变量,但是这样做不方便)。
在Linux系统上,可以通过运行命令ps axH来查看系统上当前的所有进程和线程。
虽然有非抢占线程系统,但是pthreads使用的是抢占线程管理策略,程序中的一个线程可能在任何时候被另一个线程中断。因此,上面描述的进程在时间共享系统中的随机性要素,同样出现在多线程程序的行为中。所以,使用pthreads开发的应用程序中有些程序错误不太容易重视。
Reference:
摘录自《软件调试的艺术》(The Art of Debugging with GDB, DDD and Eclipse)
分享到:
相关推荐
首先,让我们回顾一下进程的核心概念。进程是系统进行资源分配和调度的一个独立单位。它的动态性体现在它具有生命周期,即从创建、运行到终止的整个过程。在运行过程中,进程的状态会经历就绪、执行和阻塞三种基本...
本文将深入探讨Python中的异步编程概念,包括回顾多线程、多进程以及生成器,并结合提供的课件和代码示例进行详细解释。 首先,多线程是并发执行任务的一种方式。在Python中,`threading`模块提供了创建和管理线程...
《C++面向对象多线程编程》共分13章,全面讲解构建多线程架构与增量多线程编程技术。第1章介绍了用于构建面向对象程序的不同类型C++组件,以及如何使用这些组件来构建多线程...第13章对全书内容进行扼要地回顾与思考。
1. 进程线程的区别和联系 * 都是多任务编程 * 一个进程包含多个线程 * 都是动态的占有资源的,线程共享进程的资源 * 进程比线程消耗资源更多 * 进程空间独立使用特定的IPC,线程使用全局变量 2. 服务器模型 ...
(此书包含2个部分,大家下载时注意) 全书共分13章,全面讲解构建多线程架构与增量多线程编程技术。...第13章对全书内容进行扼要地回顾与思考。 本书适合用C++创建多线程组件和应用框架的程序员阅读。
在深入了解C++多线程编程之前,我们需要先对进程和线程的基本概念进行简要回顾。 ##### 进程与线程的历史背景 早期计算机系统设计时,由于硬件资源限制,一个程序独占整个系统的资源进行运行是非常普遍的做法。...
在编程领域中,多线程技术被广泛应用于提高程序的执行效率与响应性。Visual Basic(简称VB)作为一种流行的编程语言,在处理复杂的用户交互及后台任务时,多线程的支持显得尤为重要。本文将详细介绍如何在VB中实现多...
在深入探讨Java多线程与并发库的高级应用之前,我们首先需要回顾一下Java多线程的基础概念和技术要点。 ##### 1.1 线程的概念 在计算机科学中,线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是...
在讨论具体代码之前,我们先回顾一下多线程的基本概念。 ##### 1.1 什么是多线程? 多线程是指在一个进程中同时运行多个线程来执行不同的任务。每个线程都是进程的一个执行单元,它们共享相同的内存空间和其他资源...
java
编写一段程序,使用系统调用fork( )创建两个子进程,再用系统调用signal( )让父进 程捕捉键盘上来的中断信号(即按ctrl+c键),当捕捉到中断信号后,父进程用系统调用kill( )向两个子进程发出信号,子进程捕捉到信号...
6. 显示其他进程计数器:在任务管理器中,选择“性能”选项卡,显示计算机动态性能,包括 CPU 和存使用情况的图表、正在运行的句柄、线程和进程的总数、物理、核心和认可的存总数等。 7. 更改正在运行的程序的优先级...
该书全面覆盖了多线程技术的基础理论与实践应用,为开发者提供了详尽的指导。书中的"加全书签"功能使得读者能够更方便地定位和回顾关键知识点。 在Win32环境下,多线程编程是提升应用程序性能和响应性的重要手段。...
在深入探讨Linux线程实现技术之前,我们先回顾一下线程的基本概念及其在现代操作系统中的重要性。线程,作为进程中的最小可调度单位,共享同一个进程的资源,包括内存空间、文件句柄等,这使得线程间的通信更为高效...
本文将详细介绍如何利用Python实现一个多线程、异步与多进程结合的高效爬虫程序。这种爬虫不仅能够大幅提高爬取速度,还能有效处理大量请求并发的问题。 #### 二、基础概念回顾 在深入探讨具体实现之前,我们先来...