文章目录
一、进程的概念
1、进程和程序的区别:
程序:是静态的,就是个存放在磁盘里的可执行文件
进程:是动态的,是程序的一次执行过程。
进程是有生命周期的,随着程序的开始而开始,随着程序的结束而结束。
进程是最小的分配资源单位
2、进程的组成
进程包含三部分: 进程的PCB(task_struct结构体)、数据段、程序段。
创建一个进程,操作系统为该进程分配一个task_struct来标识它,同时给它分配4G的虚拟内存空间(3G用户空间,1内核空间),只要进程执行结束,分配给它的资源都会被回收。
进程=task_struct+4G(虚拟内存)
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
PCB(Process Control Block,进程控制块):
PCB是操作系统用来表示进程的数据结构,包含一个进程的所有状态信息。通常包括以下部分:
- 进程标识符:用于唯一标识一个进程(pid)
- 处理器状态信息:包括程序计数器、寄存器、堆栈指针等,用于表示进程在CPU上的执行状态
- 进程调度信息:包括进程优先级、状态(运行、就绪、阻塞等)、调度策略等,用于操作系统调度进程
- 内存管理信息:包括进程的地址空间、页表等,用于描述进程在内存中的布局
- 资源管理信息:包括打开的文件描述符、信号量、消息队列等,用于管理进程所使用的系统资源
- 其他信息:如进程创建时间、执行时间、进程间通信信息等
2.1、PCB结构体成员pid
PID:进程的唯一标识符(进程号)(PCB结构体成员之一)
它是一个大于等于0的整数,在一个系统中能够创建最大的进程号可以通过命令查看是131072个。
在系统下的/proc文件中有正在运行的进程号,进入进程号目录下打开status,里面就是进程的详细信息.
2.2、特殊的pid进程
0(idle):也称为swapper进程,在操作系统启动的时候就已经创建的进程,0号进程是1号进程和2号进程的父进程。
1(init):1号进程 是 0号进程通过kernel_thread函数创建的,它主要是用来在启动的时候初始化各种硬件,硬件初始化完之后,init进程为孤儿进程回收资源。
2(kthreadd):2号进程也是0号进程通过kernel_thread函数创建,是调度器进程。
3、进程的状态
1. 进程的状态
D: //不可中断的等待状态
R: //运行态 running
S: //可中断的等待态
T: //停止态
X: //死亡态
Z: //僵尸态
2. 进程的附加状态
<: //高优先级的进程
N: //低优先级的进程
L: //内存锁定
s: //会话组组长
l: //进程包含多线程
+: //前台进程
3.1、特殊的进程状态
-
孤儿进程: 父进程死了之后,子进程就变为孤儿进程(由1号进程回收资源)。
-
僵尸进程: 子进程死掉之后,父进程没有为子进程回收资源(收尸),这个时候子进程变为僵尸进程。
4、进程相关命令
4.1.ps命令:
ps -ef //查看所在运行的进程 主要查看进程的父子关系
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 Oct29 ? 00:00:11 /sbin/init auto noprompt
root 2 0 0 Oct29 ? 00:00:00 [kthreadd]
root 4 2 0 Oct29 ? 00:00:00 [kworker/0:0H]
root 6 2 0 Oct29 ? 00:00:00 [mm_percpu_wq]
//UID:用户名 PID:进程号 PPID:父进程号
//TTY:是否和终端有关联,没有关联就是?
ps -ajx //查看进程 可以指定名称查看 例如 ps -ajx | grep a.out 查看名为a.out的进程
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
0 1 1 1 ? -1 Ss 0 0:11 /sbin/init auto no
0 2 0 0 ? -1 S 0 0:00 [kthreadd]
2 4 0 0 ? -1 I< 0 0:00 [kworker/0:0H]
2 6 0 0 ? -1 I< 0 0:00 [mm_percpu_wq]
//只要新开一个终端就会创建一个会话SID
//一个会话内会有一个前台进程组和多个后台进程组PGID
//进程组内会有多个进程
//TTY 和终端是否有关联
//STAT 进程的状态
//TPGID 如果是-1 代表是守护进程
4.2. top/htop命令
top/htop命令:动态查看进程状态的命令
4.3. pidof命令
pidof a.out //查看所有名为a.out的进程的进程号
4.4. kill命令(给进程发信号)
kill –l 列出所有信号
kill -信号号 pid //发信号
kill -2 pid //给进程号为pid的进程发送2号信号
kill -9 pid //杀死程序
kill -19 pid //停止程序
killall name 根据进程名杀死进程
二、进程的创建(父进程创建子进程)(亲缘进程)
1、fork函数
#include <unistd.h>
函数原型:
pid_t fork(void);
返回值:
成功的话,子进程的PID号返回给父进程,0返回给子进程;
失败的话,-1返回给父进程,子进程不会创建,置位错误码。
#include <stdio.h>
#include <unistd.h>
int main(){
//创建变量承接fork函数的返回值
pid_t pid;
//fork函数创建
pid = fork(); //重点1***************************************************
//创建错误
if(pid == -1){
printf("fork error\n");return -1;
}else if(pid == 0){ //重点2***************************************************
//pid == 0子进程执行的代码
printf("tihs is child process\n");
}else{ //重点3***************************************************
//pid > 0,父进程执行的代码
printf("this is parent process\n");
}
printf("1\n");//这个地方的代码父子进程都会执行//重点4************************************
return 0;
}
2、fork创建结构图
fork n次会产生2^n个进程
3、进程注意事项
- 进程的执行没有先后顺序, 时间片轮询,上下文切换【完全随机】。
- 父子进程在空间上相互独立。
三、进程相关函数
1、getpid/getppid函数(获取进程号)
#include <sys/types.h>
#include <unistd.h>
函数原型:
pid_t getpid(void);
功能、返回值:总是成功,获取当前进程的进程号
函数原型
pid_t getppid(void);
功能、返回值:总是成功,获取当前进程的父进程的进程号
2、exit/_exit函数(退出进程)
#include <stdlib.h>
void exit(int status);
参数:
status : 进程退出时的状态
EXIT_SUCCESS
EXIT_FAILURE
功能:关闭正在执行的进程
返回值:
无
exit是库函数。进程结束时会刷新缓冲区。(和标准IO一个等级)
//---------------------------------------------------------------------------------
void _exit(int status)
参数:
status : 进程退出时的状态
EXIT_SUCCESS (0)
EXIT_FAILURE (1)
功能:关闭正在执行的进程
返回值:无
_exit是系统调用,进程结束的时候不会刷新缓冲区。 (和文件IO一个等级)
3、wait/waitpid函数(阻塞等待子进程结束,并回收子进程)
#include <sys/types.h>
#include <sys/wait.h>
函数原型:
pid_t wait(int *status);
功能:
阻塞等待子进程结束并为其回收资源,防止生成僵尸进程
参数:
status: 子进程以什么状态退出 一般写为NULL
返回值:
如果成功,返回终止子进程的进程ID 失败时,返回-1。
//-----------------------------------------------------------------------------------
#include <sys/types.h>
#include <sys/wait.h>
函数原型:
pid_t waitpid(pid_t pid, int *wstatus, int options);
功能:回收指定进程号的子进程,可以设置是否阻塞。
参数:
- pid:
pid > 0 : 某个子进程的pid
pid = 0 : 回收当前进程组的所有子进程
pid = -1 : 回收所有的子进程,相当于 wait() (最常用)
pid < -1 : 某个进程组的组id的绝对值,回收指定进程组中的子进程
- options:设置阻塞或者非阻塞
0 : 阻塞
WNOHANG : 非阻塞
返回值:
> 0 : 返回子进程的id
= 0 : options=WNOHANG, 表示还有子进程或者
= -1 :错误,或者没有子进程了
4、exec函数族(替换进程)(待补充)
5.示例
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
int main(){
pid_t pid1, pid2;
//第一个子进程
if((pid1 = fork())== 0){
sleep(3);
printf("1: child process 1\n");
exit(0);
printf("1: child process 2\n");
}else{//父进程
if( (pid2 = fork()) == 0)//第二个子进程
{
sleep(1);
printf("2: child process 1\n");
while(1);
exit(0);
}else{
wait(NULL);
wait(NULL);
printf("3: parent process 1\n");
printf("3: parent process 2");
}
}
return 0;
}