一、进程的概念
1.程序与进程的区别
程序:编译后产生的,格式为ELF的,存储于硬盘的文件。可以通过 readelf -s [文件名] 查看文件信息 进程:程序中的代码和数据,被加载到内存中运行的过程。当程序被CPU加载时,根据每一行代码做出相应的效果,形成动态的过程,那么这个过程就是进程。 其实说白了,进程就是一个正在执行的程序。 程序是静态的概念,进程是动态的概念
2 .开启进程
直接在linux下,执行一个程序,就会开启相应的进程。
例如: ./main -> 开启一个名字为hello的进程。
3当进程开启之后,系统会为进程分配的资源
(1)会分配进程对应内存空间
int x; //运行程序后,会向栈空间申请四个字节的空间
(2)进程在系统内核中如何进行表示呢
学生管理系统 ----------->每个学生使用结构体进行表示和管理
linux系统 ----------->每个进程使用结构体进行表示和管理
当进程开启之后,会为这个进程分配一个任务结构体,这个任务结构体就是用于描述这个进程的。也就是说,进程在内核中是以结构体struct task_struct{} 进行表示的。这个结构体也被称之为进程控制块。
结构体:进程ID号、信号、文件、资源....
/usr/src/linux-headers-3.5.0-23/include/linux/sched.h
二、关于进程的命令
1.可以使用命令pstree查看这些进程的关系
可以看到,最开始的系统进程叫systemd,这个进程的诞生比较特别,其身份信息在系统启动前就已经存在于系统分区之中,在系统启动时直接复制到内存。
2.ps查看进程ID号
ps -ef/-elf 静态显示
3.top查看进程CPU的占用率
三、进程的状态
1.什么是僵尸态?
进程结束时,就从运行态变成僵尸态,所谓僵尸态,就是代表这个进程所占用的CPU资源和自身的任务结构体没有被释放,这个状态的进程就是僵尸态进程。
2.总结:
1)进程在暂停态时,收到继续的信号时,是切换到就绪态,而不是运行态。
2)程序的main函数执行return 0就会导致进程的退出,一定会变成僵尸态。
3)进程不可以没有父进程,也不能同时拥有两个父进程。
4)孤儿进程特征就是失去父进程时,会马上寻找继父,而不是等到孤儿进程变成僵尸态再找。
5)祖先进程一定要帮其他的进程回收资源。
四、进程的创建
1.创建一个进程
pid_t fork(void); // 返回值 失败-1
// 大于0 id号代表子进程的ID号 =0
结果1:父进程先运行,子进程后运行
在这里,只有父进程退出,才会出现命令行,子进程退出是不会出现命令行
结果2:子进程先运行,父进程后运行
2.想确保子进程先运行,就要父进程先睡眠
getpid----》返回自己的ID号
getppid---》返回父进程的ID号
五、僵尸进程和孤儿进程
1.概念
孤儿进程:一般情况下,调用fork()函数创建的子进程,父进程如果比子进程先退出,那么这个子进程称之为 孤儿进程。那么,祖先进程systemd 就会成为该子进程的父进程,回收该子进程的资源。
僵尸进程:父进程还存在,但是去做的别的事情了(比如在一个死循环,没有退出),此时子进程退出之后,就变成了僵尸进程。
(可以用ps -ef 查看,进程的状态栏为defunct,这就是所谓的“僵尸”进程)
2.僵尸进程![](https://i-blog.csdnimg.cn/direct/19e977319ae04554bddf8cfbaf5b0ac1.png)
![](https://i-blog.csdnimg.cn/direct/4650be6c24514f0e8eedbdfaa24bf274.png)
3.孤儿进程
4、解决僵尸态问题
父进程应当调用wait()
或waitpid()
函数来等待子进程的结束,并回收子进程的资源。这是解决僵尸进程问题的最直接方法。
(1)wait()
pid_t wait(int *status);
int *status
:这是一个指向整数的指针,用于接收子进程的退出状态。这个参数是可选的,如果你不关心子进程的退出状态,可以传递NULL
。如果传递了一个非NULL
的指针,系统将通过该指针返回子进程的退出状态信息。pid_t
:函数返回结束的子进程的PID。如果调用进程没有子进程,则返回-1,并设置errno为ECHILD。如果出现其他错误,也会返回-1,但errno会设置为相应的错误代码。
(2)waitpid()
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *status, int options);
参数
pid
:指定要等待的子进程的PID。
- 如果
pid
大于 0,则等待与pid
相等的子进程。- 如果
pid
等于 0,则等待任何子进程(与wait()
类似,但具有options
提供的额外控制)。- 如果
pid
等于 -1,则等待任何子进程,其行为与pid
为 0 时类似,但某些系统实现可能会为-1
提供不同的处理(如处理孤儿进程)。- 如果
pid
小于 -1,则等待组ID等于pid
绝对值的任何子进程。
status
:指向整数的指针,用于接收子进程的退出状态。与wait()
一样,这个参数是可选的。
options
:一个或多个选项标志的位或(bitwise OR),用于修改waitpid()
的行为。常见的选项包括:
WNOHANG
:如果指定的子进程没有结束,则立即返回0,而不是阻塞。WUNTRACED
:返回因停止信号而停止的子进程的状态。返回值
- 成功时,
waitpid()
返回结束或停止的子进程的PID。- 如果
WNOHANG
被设置且没有子进程结束,则返回0。- 如果出现错误,则返回-1,并设置errno以指示错误。
六、进程的退出与回收
1、exit()
#include <stdlib.h>
void exit(int status);
- 功能:终止当前进程,执行清理操作(如调用
atexit()
注册的函数、刷新标准I/O缓冲区),并返回给操作系统一个状态码。- 参数:
int status
(整型),表示进程的退出状态码。通常,0 表示成功,非0 值表示某种错误或特定状态。- 头文件:
<stdlib.h>
2._exit()
- 功能:立即终止当前进程,不进行任何清理操作(如调用
atexit()
注册的函数、不刷新标准I/O缓冲区),并返回给操作系统一个状态码。- 参数:
int status
(整型),表示进程的退出状态码。- 头文件:
<unistd.h>
(注意,这个头文件在Windows中不可用,是POSIX系统的一部分)
3._Exit()
- 功能:与
_exit()
类似,立即终止当前进程,不进行任何清理操作,并返回给操作系统一个状态码。它是C99标准中引入的,旨在提供一种可移植的方式来执行_exit()
的功能。- 参数:
int status
(整型),表示进程的退出状态码。- 头文件:
<stdlib.h>
(注意,尽管_Exit()
在<stdlib.h>
中声明,但它的实现可能依赖于系统调用_exit()
,后者通常在<unistd.h>
中定义)