一. 进程和线程
进程和线程的存在目的都是为了实现并发执行,提高系统的资源利用率和响应速度。
进程
概念:
自己话理解,进程就是,一个程序,当操作系统执行时,让他成为了一个动起来的实体,此时这个活动的实体就是进程。
- 进程是程序执行时的一个实例。每个进程都有自己的地址空间、内存、数据栈以及其他用于跟踪进程执行的辅助数据。
- 进程是操作系统进行资源分配和调度的基本单位。每个进程都拥有独立的系统资源,如内存空间、文件句柄等。
- 进程之间相互独立,彼此之间不能直接访问对方的数据。如果一个进程崩溃,通常不会影响其他进程的执行。
- 创建和销毁进程的开销比较大,因为需要为每个进程分配独立的内存空间和资源。
- 进程之间通信需要内核的介入,以提供保护和通信所需的机制,通信的方式包括管道、消息队列、信号量、共享内存等。
产生的原因:
在最开始没有操作系统的时候,电脑处理任务都是按顺序执行,一个任务在处理期间是独占了整个电脑资源。任务的运行需要CPU、输入输出设备等一起协同工作,但是由于CPU运行的很快,而输入输出设备运行的很慢,所以往往大部分时间CPU都处于空闲状态,等待输入输出的完成。
因此,出现了所以就出现了支持多道程序运行的系统,当一个任务再出现耗时的操作时,cpu就会转向执行别的需要cpu资源的任务。而多个任务进入内存并运行,出现以下问题:
- 多任务如何进行区分?
- 当某个任务因为等待I/O暂停时,怎么恢复到之前的运行状态?
此时,就发明了进程这个概念,用进程来保存每个任务的数据和运行状态,同时对每个进程划分对应的内存地址空间(代码、数据、进程空间、打开的文件),并且要求进程只能使用它自己的内存空间,从而来达到任务的区分和恢复。
优劣势:
进程的优势是提供了很好的隔离性,操作系统会为每个进程分配独立的内存空间和资源,不会互相影响;
但由于相互独立,彼此不能直接访问对方的数据,因此进程之间通信需要内核的介入,以提供保护和通信所需的机制,通信的方式包括管道、消息队列、信号量、共享内存等。
多进程:
多进程是指在操作系统中同时运行多个独立的进程。这些进程具有各自独立的内存空间和资源,并且可以并发地在 CPU 上执行。操作系统会通过进程调度算法来分配 CPU 时间片给不同的进程,从而实现多任务并发执行的效果。
在多进程编程中,每个进程都有自己的代码段、数据段和堆栈,彼此之间互相独立。多个进程可以同时执行不同的任务,它们之间可以通过进程间通信机制进行通信和同步。
适用场景:
由于多进程的特性,它适合于不需要数据交互,能充分利用cpu资源的场景。也就是适合任务独立的场景
- cpu密集型任务:程序需要大量的cpu计算时,可以适用多进程充分利用多核cpu,很大程度避免了进程切换的问题。
- 并行计算:在需要进行并行计算的应用中,因为进程之间独立,不会互相影响,多进程可以实现真正的并行执行,每个进程独享一部分系统资源。 (多线程之间存在资源竞争和数据访问冲突等问题)
线程
概念:
线程包含在进程中,是进程中的实际运作单位,是程序执行的最小单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发执行多个线程,每条线程并行执行不同的任务。
- 线程是进程中的一个执行流程,一个进程可以拥有多个线程,这些线程共享进程的资源。
- 进程中的线程之间共享相同的地址空间和其他进程资源,如打开的文件和信号处理等。因此,线程之间的通信和数据共享更加容易。
- 线程相比于进程更加轻量级,创建和销毁线程的开销较小,线程切换的开销也较小。
- 由于线程共享进程的资源,因此线程之间的同步和互斥需要额外的手段来保证数据的一致性和正确性,如互斥锁、信号量、条件变量等。
产生的原因:
随着进程的出现,我们发现,只使用进程来处理程序的并发,是不够的。因为进程在一个时间段只能做一件事,如果要并发做别的事,我们就需要不断的切换进程。但我们知道由于进程之间相互独立,切换时候需要保存和回复大量进程的上下文,切换开销比较大。
因此,为了避免进程切换开销大的弊端,发明了线程。使用线程表示进程中的不同任务,同时又将计算机实际的调度单元转到线程。这样就避难了内存地址空间的切换,也达到了多任务的并发执行。
多线程:
多线程是指在一个进程内部同时运行多个线程,这些线程共享相同的内存空间和资源,可以并发地在 CPU 上执行。
在多线程编程中,每个线程都有自己的堆栈,用于管理线程执行过程中的函数调用、局部变量和临时数据等信息。但线程共享进程的地址空间和其他资源,比如全局变量、打开的文件等。由于线程之间共享相同的地址空间,它们可以更方便地进行通信和同步。
多线程通常用于实现并发执行的程序,可以在单个进程内部同时执行多个任务,提高系统的效率和性能。由于线程共享相同的地址空间和资源,因此上下文的切换通常只需保存和恢复寄存器状态、程序计数器和堆栈指针等少量信息,所以线程间的切换开销通常比进程间的切换开销小,这使得多线程编程在某些场景下比多进程编程更为高效。
需要注意的是,多线程编程也需要考虑线程安全性和同步机制,以避免竞态条件和数据访问冲突等问题。
适用场景:
多线程之间互相内存空间,因此可以直接读写共享数据,适合用于有数据交互的场景。
- I/O密集型任务:当程序需要进行大量的I/O操作(如文件读写、网络通信等)时,可以使用多线程来提高效率,因为在I/O操作时,CPU大部分时间处于空闲状态,可以让其他线程继续执行。
- GUI应用程序:在用户界面程序中,需要保持UI的响应性,而且有很多后台任务需要同时执行,这时可以使用多线程来处理后台任务,以免阻塞主线程导致UI无响应。
- 异步编程:在异步编程中,程序可以在执行耗时操作的同时继续执行其他任务,而不必等待耗时操作完成。通过多线程可以很方便地实现异步编程。
总结
总的来说,多线程和多进程之间各有利弊,需要根据具体的场景和需求进行选择。
二. 程序的底层执行过程
通常涉及预处理、编译、汇编、链接、加载和执行这几个步骤
(例如一个xxx.c源程序)
- 预处理:预处理器根据字符“#”开头的命令,读取头文件里的内容,并将它插入程序文本中,得到另一个xxx.i源程序。
- 编译:源代码被编译器翻译成汇编指令,得到xxx.s文件。
- 汇编:汇编器将xxx.s文件翻译成机器语言指令,并将其打包为目标文件,得到xxxx.o文件。
- 链接:链接器将多个目标文件和库文件链接成最终的可执行文件xxx。
- 加载:加载器将可执行文件加载到内存中。这包括分配内存空间以及将可执行文件的代码和数据加载到适当的内存位置。
- 执行:
- 当程序被加载到内存中后,操作系统将控制权转移到程序的入口点(例如main函数)。
- 程序开始执行,并按照编写的指令执行相应的操作,例如计算、IO操作等。
- 在程序执行过程中,可能会调用操作系统提供的系统调用来进行诸如文件操作、网络通信等底层操作。
- 运行时:
- 在程序执行期间,操作系统负责管理程序的内存、CPU资源等,并提供必要的服务,如进程间通信、异常处理等。
- 操作系统可能会在必要时对程序进行调度,以确保多个进程或线程之间的公平共享CPU资源。
- 终止:
- 当程序执行完毕或发生错误时,程序将退出并释放其占用的资源。
- 操作系统可能会清理程序的内存空间,并将进程状态更新为终止状态。
这些步骤构成了一个程序从源代码到最终执行的整个底层过程。在不同的操作系统和编程语言环境下,这些过程可能会有所不同,但通常都包括类似的步骤。
注意:
1.在加载过程中,程序变成了进程。加载器将可执行文件加载到内存中时,操作系统会为该程序分配一些系统资源,例如内存空间、文件描述符等,并为其创建一个进程控制块(PCB)来管理该进程的状态、上下文等信息。因此,当程序开始执行时,它已经成为了一个进程。
2.段错误是指程序试图访问未分配给它的内存段(segment)或试图对只读内存段进行写操作,从而导致操作系统中止该程序的执行。这通常是由于编程错误导致的,比如访问空指针或者数组越界等问题。
标签:多线程,操作系统,程序,理解,线程,进程,执行 From: https://www.cnblogs.com/cs-whx/p/18117341