一、进程基本概念
1. 程序与进程
-
程序:静态的,存储在硬盘上的指令和数据的集合。
-
进程:程序的一次执行过程,是系统进行资源分配和调度的基本单位,具有创建、执行、调度和终止的生命周期。
二、进程相关命令
1. 进程查看
-
top:实时查看系统进程及资源占用情况。 -
ps -ef:查看系统所有进程的详细信息。 -
ps -aux:查看进程状态、CPU和内存使用情况。 -
ps -ef | grep 进程名:查找指定进程。
2. 进程控制
-
kill -9 PID:强制终止指定PID的进程。 -
killall -9 进程名:终止所有同名进程。 -
&:在后台运行程序,如./a.out &。 -
jobs:查看当前终端的所有后台任务。 -
fg 编号:将后台任务调至前台执行。 -
nice -n 优先级 任务:以指定优先级运行进程。 -
renice -n 优先级 PID:修改运行中进程的优先级。
三、进程的创建与地址空间
1. 虚拟地址与物理地址
-
虚拟地址:通过MMU映射后进程可访问的内存空间。
-
物理地址:实际的RAM地址,用户无法直接访问,需通过虚拟地址映射。
2. 虚拟地址空间布局(0-4G)
-
文本段 (.text):存放程序代码。
-
数据段:
-
.rodata:只读数据(如字符串常量)。 -
.data:已初始化的全局变量和静态变量。 -
.bss:未初始化的全局变量和静态变量(进程启动时清零)。
-
-
栈区 (.stack):存放局部变量,默认8M,由高向低增长。
-
堆区 (.heap):动态分配内存区域,由低向高增长。
-
内核空间:用户无法直接访问。

3. 进程空间独立性
- 每个进程拥有独立的虚拟地址空间,映射到不同的物理内存区域,确保进程间互不干扰。
四、进程调度算法
-
先来先服务 (FCFS)
-
短作业优先 (SJF)
-
高优先级调度
-
时间片轮转 (RR):每个进程分配一个时间片(通常5-10ms),宏观上并行,微观上串行。
-
多级队列反馈调度
-
负载均衡调度
-
抢占式调度

五、进程状态
-
运行态 (R):正在CPU执行。
-
就绪态 (R):已准备好,等待CPU调度。
-
可唤醒等待态 (S):等待资源,可被唤醒。
-
不可唤醒等待态 (D):等待资源,不可中断。
-
停止态 (T):被用户暂停。
-
僵尸态 (Z):进程已结束,资源未回收。
-
结束态 (X):进程结束且资源已回收。
六、进程相关函数接口
1. fork() -- 创建子进程
c
pid_t fork(void);
-
子进程复制父进程的代码、数据、堆栈等空间。
-
父进程返回子进程PID,子进程返回0,失败返回-1。
2. getpid() -- 获取当前进程PID
c
pid_t getpid(void);
3. getppid() -- 获取父进程PID
c
pid_t getppid(void);
七、编程练习与实践
练习1:创建子进程并打印PID
创建两个子进程,分别打印自己的PID和父进程PID,父进程打印自己的PID和两个子进程的PID。
末尾的while(1)也可以不用,但要再父进程打印那里加上一个sleep(5)函数,这是为了防止父进程提前结束,使得子进程的getppid()函数返回值错误
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void)
{
pid_t ret1 = 0;
pid_t ret2 = 0;
ret1 = fork();
if(-1 == ret1)
{
perror("fail to fork");
return -1;
}
if(0 == ret1)
{
printf("我是子进程1: pid : %d ppid: %d\n", getpid(), getppid());
}
else if(ret1 > 0)
{
ret2 = fork();
if(-1 == ret2)
{
perror("fail to fork");
return -1;
}
if(0 == ret2)
{
printf("我是子进程2: pid : %d ppid: %d\n", getpid(), getppid());
}
else if(ret2 > 0)
{
printf("我是父进程: pid : %d childpid1: %d childpid2: %d\n", getpid(), ret1, ret2);
}
}
while(1)
{
}
return 0;
}
练习2:遍历目录查找媒体文件
遍历指定目录,打印所有以 .flv、.avi、.rmvb、.rm 结尾的文件。


