一、进程与线程
进程(Process):
-
定义: 进程是操作系统中一个正在运行的程序的实例。每个进程都有自己的地址空间、内存、数据栈以及其他系统资源的副本。
-
特点:
- 每个进程都是独立的,它们之间不能直接共享数据,需要通过进程间通信(IPC)的方式来实现数据传递。
- 进程拥有自己的地址空间,一个进程的崩溃不会影响其他进程。
-
优点:
- 稳定性高:一个进程的崩溃不会影响其他进程。
- 安全性高:由于进程间的隔离性,数据不容易被其他进程非法访问。
-
缺点:
- 资源开销大:每个进程都有自己的独立内存空间,占用较多的系统资源。
- 切换代价高:由于进程切换需要保存和恢复整个进程的状态,切换代价相对较高。
线程(Thread):
-
定义: 线程是进程的一部分,是进程内的一个执行单元。一个进程可以包含多个线程,它们共享相同的地址空间和系统资源。
-
特点:
- 线程之间共享进程的资源,包括内存和文件句柄等。
- 线程更轻量,创建和切换的代价较低。
-
优点:
- 资源开销相对较小:多个线程可以共享同一进程的资源。
- 切换代价低:线程切换的代价较进程切换低。
-
缺点:
- 稳定性较差:一个线程的崩溃可能会影响整个进程。
- 安全性较低:由于线程共享同一进程的资源,需要通过同步机制来保证数据的安全性。
二、Linux中的进程和线程
在Linux系统中,进程和线程的概念与一般的操作系统类似,但有一些特定的实现和命令行工具可以用来管理和监控它们。
进程:
-
进程的创建:
- 在Linux中,使用系统调用
fork()
可以创建一个新的进程。新进程是原进程的副本,但有不同的进程ID。 exec()
系统调用可以用于在一个进程中执行新的程序。
- 在Linux中,使用系统调用
-
进程的状态:
- 进程在运行时可能处于不同的状态,如运行(Running)、就绪(Ready)、等待(Waiting)等。
-
进程的管理:
ps
命令用于列出当前运行的进程。kill
命令用于终止一个进程。top
命令用于实时查看系统的进程状态。
线程:
-
线程的创建:
- 在Linux中,线程是通过
pthread
库进行创建和管理的,通常使用pthread_create()
函数。 - 线程在同一个进程中共享相同的地址空间和其他资源。
- 在Linux中,线程是通过
-
线程的管理:
ps -eLf
命令可以列出所有线程。kill
命令同样可以用于终止一个线程。pthread_join()
函数可以等待一个线程的结束。
-
线程同步:
- Linux提供了多种线程同步的机制,如互斥锁(Mutex)、条件变量(Condition Variable)等,用于协调线程之间的操作。
-
线程库:
- Linux支持多种线程库,其中最常见的是 POSIX 线程库(
pthread
),它提供了一套标准的API,可用于跨平台的线程编程。
- Linux支持多种线程库,其中最常见的是 POSIX 线程库(
三、进线程示例
进程示例:
1.查看当前运行的进程
ps aux
这会显示当前系统上所有的进程,包括它们的进程ID、状态、运行时间等信息。
2.创建一个新的进程
# 在后台运行一个示例程序,例如一个无限循环
nohup bash -c "while true; do echo 'Hello, process!'; sleep 1; done" &
这个命令创建了一个后台进程,其中一个简单的无限循环输出 "Hello, process!"
3.终止一个进程
# 查找进程ID
ps aux | grep "Hello, process!"
# 使用kill命令终止进程
kill -9 <进程ID>
在这个例子中,你需要替换 <进程ID>
为实际的进程ID。
线程示例:
创建一个使用pthread的C程序,编译并运行:
// filename: thread_example.c
#include <pthread.h>
#include <stdio.h>
void *thread_function(void *arg) {
for (int i = 0; i < 5; ++i) {
printf("Hello, thread! %d\n", i);
sleep(1);
}
pthread_exit(NULL);
}
int main() {
pthread_t thread_id;
pthread_create(&thread_id, NULL, thread_function, NULL);
pthread_join(thread_id, NULL);
printf("Thread finished!\n");
return 0;
}
这个简单的C程序创建了一个新的线程,该线程输出 "Hello, thread!" 五次。
编译并运行:
gcc -o thread_example thread_example.c -pthread
./thread_example
这里,-pthread
标志用于链接 pthread 库。
考点(老师上课的重点)
进程控制块(Process Control Block,PCB)是操作系统中用于管理和维护进程信息的数据结构。每个进程在系统中都有一个对应的PCB,它包含了进程的各种状态、上下文和控制信息。
PCB 存储了一个进程的关键信息,以便在进程切换时能够恢复和保存其状态。以下是一般情况下 PCB 包含的主要信息:
-
进程标识符(Process ID):
- 用于唯一标识一个进程。
-
程序计数器(Program Counter):
- 存储了下一条将要执行的指令的地址。
-
寄存器集合:
- 包含了进程的各个寄存器的值,包括通用寄存器、栈指针、程序状态字等。
-
进程状态(Process State):
- 进程可以处于运行、就绪、阻塞等不同的状态,PCB 中保存了当前状态。
-
进程优先级(Priority):
- 用于确定进程在调度时的优先级。
-
进程调度信息:
- 包括进程的调度队列信息,例如就绪队列中的位置等。
-
内存管理信息:
- 进程在内存中的分配情况,包括基址、界限寄存器等。
-
打开文件表(File Descriptor Table):
- 指向进程打开文件的信息,包括文件描述符、文件位置等。
-
父进程标识符(Parent Process ID):
- 记录了创建该进程的父进程的标识符。
-
其他控制信息:
- 包括信号处理、定时器等额外的控制信息。
PCB 的主要作用是在进程切换时保存当前进程的状态,并在需要时恢复该状态。当一个进程被操作系统挂起(从运行状态切换到等待或就绪状态)时,它的 PCB 就会被保存。当进程再次被调度执行时,系统将恢复该进程的 PCB,使其能够继续执行。 PCB 是实现多任务操作系统中进程管理的关键数据结构之一。