对进程的小结:
- 什么是进程?
进程就是正在运行的程序。
站在操作系统的角度上讲,进程就是pcb,linux下的pcb是task_struct
2. 进程的管理(从描述和组织两个角度讲)
描述:使用结构体描述进程的属性(这里的结构体值得是task_struct)
Task_struct里面的主要内容:
1):标识符,即就是pid(或id),是描述进程的唯一 标示符,用来区别其他进程同一台主机上不同进程的pid不同
2):内存指针,包括程序代码和进程相关数据的指针,还有和其他进程共享的内存指针
3)辅助操作系统进行进程调度的属性
a. 优先级,不同的进程有优先级之分,这决定了进程被调度在CPU上的先后顺序
b. 上下文数据:进程执行时保存在寄存器中的数据,
c. 程序计数器:保存程序中将要执行的下一条指令的地址
d. I/O状态信息:包括显示的I/O请求,分配给I/O设备和被进程使用的I/O列表
e.记账信息
f. 状态:任务信息、退出码、退出信号等信息
组织: 一般采用双向链表对进程进行组织
3. 进程的创建
- 进程的创建采用fork函数,进程创建出来必须加载到物理内存
fork:(以父进程为模版创建子进程)
- 有两个返回值,父进程返回子进程的pid,子进程返回0,创建失败返回-1
- Fork之后父子进程的代码是共享的,数据是以拷贝的形式各自私有一份
- fork 之后父子进程完全没有关系,谁先执行完全取决于调度器,而且fork之后,在原则上父进程应该等待子进程,回收子进程的退出状态
- 子进程拥有自己的虚拟地址空间
4.进程的退出
1)进程的退出场景:
a.程序运行完,结果正确
b.程序运行完,结果不正确
c.异常退出
2) 进程的退出方式:
a. return
b. exit
c. _exit
三者的区别:
Return只在main函数中才表示退出码,exit在任何地方调用,一旦调用则表示进程退出
_exit() 和 exit()的区别:
_exit()强制终止进程,exit()在终止进程之前会关闭文件标识符、清空缓冲流
3)进程的退出码
Sterror
Perror
5.进程等待
1) 进程为什么需要等待?
答:为了避免僵尸进程
僵尸进程:子进程先于父进程退出,父进程没有关注子进程的退出状态,造成内存泄漏
若父进程先于子进程退出,那么该子进程就变成孤儿进程。
2)如何进行等待?
等待的方式:阻塞式等待和非阻塞是等待
- 阻塞式等待:
为了完成一个功能发起一个函数调用,如果没有完成这个功能则一直挂起等待功能完成才返回
- 非阻塞式等待
为了完成一个功能发起一个函数调用,如果此时不具有完成的条件,则立即返回而不等待
pid_t wait (int *status);
Wait: 等待任意一个子进程退出,若没有子进程退出,则一直阻塞等待
pid_t waitpid (pid_t pid, int *status, int options);
Wait pid :可以等待指定的子进程,也可以等待任意一个子进程,取决于第一个参数
Wait 是一个阻塞式等待函数,必须等到有一个子进程退出获取状态释放资源后才返回
3)进程的退出状态获取
在wait的参数中存储了子进程的退出原因以及退出码,而参数中只用了低16位的两个字节用于存储这些信息
在这低16位中,高8位存储的是退出码,程序运行完毕退出才会有
低8位存储的值引起异常退出的信号值,当程序异常退出时,状态码则为0
6. 进程的程序替换
六种替换函数
#include <unistd.h>
extern char **environ;
int execl (const char *path, const char *arg, ...);
int execlp (const char *file, const char *arg, ...);
int execle (const char *path, const char *arg, ..., char * const envp[]);
Int execv (const char *path, char *const argv[]);
int execvp (const char *file, char *const argv[]);
int execvpe (const char *file, char *const argv[], char *const envp[]);
execl 与 execle 的区别
execl :继承于父进程的环境变量
execle : 由用户自己组织环境变量
execl 与exec 的区别
execl函数需要我们明确告诉操作系统,这个替换的程序在哪里
exec 函数族作用是程序替换,如果替换成功,代表运行的代码已经不是以前的代码段了,而是新程序,因此原来代码exec以后的代码都不会运行,除非出错
execlp函数只需要告诉操作系统要替换的名称即可