Linux环境编程05

本文详细介绍了Linux进程管理,包括进程的基本概念、分类、查看进程的方法、进程标识符、父进程与子进程的关系、进程创建(fork和vfork)、进程退出方式、异常终止情况以及子进程的回收。重点讲解了如何使用fork、exec系列函数创建和管理进程,以及wait和waitpid函数在回收子进程中的作用。
摘要由CSDN通过智能技术生成

Linux进程管理

一、进程的基本概念

1、进程与程序

​ 程序是存储在磁盘上的可执行文件,程序被加载到内存中开始运行时叫做进程

​ 一个程序可以被多次加载生成多个进程,进程就是处于活动状态的计算机程序

2、进程的分类

​ 进程一般分为三个种类:交互进程、批处理进程、守护进程

3、查看进程

​ 简单模式:ps 显示当前用户终端控制的进程简单信息

​ 列表模式:ps -auxw 显示所有进程的详细信息

​ a 所有用户有终端控制的进程

​ x 无终端控制的进程

​ u 显示进程的详细信息

​ w 以更大的列宽显示

​ USER 进程的属主用户名

​ PID 进程号

​ %CPU CPU使用率

​ %MEM 内存使用率

​ VSZ 虚拟内存使用的字节数

​ RSS 物理内存使用的字节数

​ TTY 终端设备号 ?表示无终端控制

​ STAT 进程的状态

​ O 就绪态 等待被调用

​ R 运行态 Linux系统没有O,就绪也用R表示

​ S 可被唤醒的睡眠态,如系统终端、获取资源、收到信号等都可以唤醒进入运行态

​ D 不可被唤醒的睡眠态,只能被系统唤醒

​ T 暂停态 收到SIGTSTP信号进入暂停态,收到SIGCONT信号转回运行态

​ X 死亡态

​ Z 僵尸态 僵死态

​ N 低优先级

​ < 高优先级

​ l 多线程进程

​ s 进程领导者

​ START 进程启动时间

​ TIME 进程运行时间

​ COMMAND 启动进程的命令

4、父进程、子进程、孤儿进程、僵尸进程

​ 一个进程可以被另一个进程创建,创建者叫做父进程,被创建者叫子进程,子进程被父进程创建后会操作系统的调度下同时运行

​ 当子进程先于父进程结束,死前子进程会向父进程发送信号SIGCHLD,此时

​ 父进程应该去回收子进程的相关资源

孤儿进程:父进程先于子进程结束,子进程就变成了孤儿进程,孤儿进程会被

​ 孤儿院(init守护进程)领养

​ init就是孤儿进程的父进程

僵尸进程:该进程已死亡,但是它的父进程没有立即回收它的相关资源,该进程

​ 就进入僵尸态

5、进程标识符

​ 每个进程都有一个用非负整数表示的唯一标识,记为进程ID\PID

​ 进程ID在任意时刻都是唯一的,但是可以重新使用,进程一旦结束它的进程ID就

​ 会被系统回收,过一段时间后再重新分配给其他新创建的进程使用(延时重用)

pid_t getpid(void);

功能:返回调用者的进程ID

pid_t getppid(void);

功能:返回调用者的父进程ID

二、创建进程

pid_t fork(void);

功能:创建子进程

返回值:一次调用两次返回,子进程返回0,父进程返回子进程的ID,但进程数量超过系统的

限制时会创建失败,返回-1

1、通过fork创建的子进程会拷贝父进程(数据段、bss段、堆、栈、I/O缓冲区),与父进程共享

代码段、子进程会继承父进程的信号处理方式

2、fork函数调用后父子进程各自独立运行,谁先返回不确定,但是可以通过睡眠usleep()确定让哪个进程先

执行

3、通过fork创建的子进程可以共享父进程的文件描述符

4、可以根据返回值的不同让父子进程进入不同的分支,执行不同的代码

练习1:为进程创建4个子进程,再为这4个子进程,分别创2个子进程 13个进程

​ 解题思路:子进程创建后,执行完任务后就休眠,这样不会被其它的fork()影响

pid_t vfork(void);

功能:以加载可执行文件的方式来创建子进程

返回值:子进程返回0,父进程返回子进程的ID

注意:vfork创建的子进程一定先返回,此时子进程并没有

创建成功,需要加载一个可执行文件替换当前子进程当前的

所有资源,当替换完成后子进程才算创建成功,此刻父进程才返回

使用exec 系列函数让子进程加载可执行文件

extern char **environ;

int execl(const char *path, const char *arg, .../* (char *) NULL */);

path:可执行文件的路径

arg:命令行参数,个数不定,由实际的可执行文件所需命令行参数决定

​ 一般第一个是可执行文件的名字,至少有一个,一定要以NULL结尾

int execlp(const char *file, const char *arg, .../* (char *) NULL */);

file:可执行文件名字

arg:命令行参数,同上

int execle(const char *path, const char *arg, .../*, (char *) NULL, char * const envp[] */);

path:可执行文件的路径

arg:命令行参数,同上

envp:环境变量表,父进程可以在加载子进程时把环境变量表传递给子进程

int execv(const char *path, char *const argv[]);

path:可执行文件的路径

argv:命令行参数数组,最后以NULL结尾

int execvp(const char *file, char *const argv[]);

file:可执行文件名字

argv:命令行参数,同上

注意:也是根据PATH的路径加载file

int execvpe(const char *file, char *const argv[],char *const envp[]);

file:可执行文件名字

argv:命令行参数数组,同上

envp:环境变量表

注意:也是根据PATH的路径加载file

​ exec系列函数正常情况下是不会返回的,当子进程加载失败时才会返回-1

​ 虽然通过vfork、exec系列函数创建加载的子进程不会继承父进程的信号处理函数,但是能

​ 继承父进程的信号屏蔽集

三、进程的正常退出

1、 在main函数中执行 return n,该返回值可以被父进程获取,几乎与exit等价

2、 进程调用了exit函数,该函数是标准库函数

void exit(int status);

功能:在任何时间、地点调用该函数都可以立即结束进程

status:结束状态码(EXIT_SUCCESS\EXIT_FAILURE)

​ return 的返回值效果是一样的

返回值:该函数不会返回

​ 进程退出前要完成:

​ 1、先调用事先通通过atexit\on_exit函数注册的函数,如果都注册了

​ 执行顺序与注册顺序相反

​ int atexit(void (*function)(void));

​ 功能:向内核注册一个进程结束前必须调用的函数

​ int on_exit(void (*function)(int , void *), void *arg);

​ 功能:向内核注册一个进程结束前必须调用的函数

​ arg:会在调用function时传给它

​ 2、冲刷并关闭所有打开状态的标准IO流

​ 3、底层继续调用_Exit/_exit函数

3、 调用_Exit/_exit

​ void _exit(int status);

​ 功能:结束进程,由系统提供的

​ void _Exit(int status);

​ 功能:结束进程,由标准库提供的

​ 1、它们的参数会被父进程获取到

​ 2、进程结束前会关闭所有处于打开状态的文件描述符

​ 3、向父进程发送信号SIGCHL(17)

​ 4、该函数也不会返回

4、进程的最后一个线程执行了return返回语句

5、进程的最后一个线程执行了pthread_exit函数

四、进程的异常终止:

1、进程调用了abort函数,产生 SIGABRT(6)信号

2、进程接收到某些信号,可以是其他进程发送的,也可能自己的错误导致的

3、进程的最后一个线程接收到 "取消"请求操作,并响应

这三种方式结束进程,它的父进程都无法获取结束状态码,因此叫做异常终止

注意:无论进程是如何结束的,它们最后都会执行同一段代码,会关闭所有

打开的文件,并释放所有的内存

五、子进程的回收

对于子进程的结束而言,都希望父进程能够知道并作出一定的反应,通过wait waitpid 函数

可以知道子进程是如何结束的以及它的结束状态码

#include <sys/wait.h>

pid_t wait(int *status);

功能:等待子进程结束,并获取结束状态码

status:输出型参数,接收结束状态码

返回值:结束的子进程的ID

​ 1、如果所有子进程都还在运行,则阻塞

​ 2、如果有一个子进程结束,立即返回该进程的结束状态码和ID

​ 3、如果没有子进程返回-1

pid_t waitpid(pid_t pid, int *status, int options);

功能:等待回收指定的某个或某些进程

pid

​ >0 等待该进程结束

​ 0 等待同组的任意进程结束

​ -1 等待任意进程结束,功能与wait等价

​ <-1 等待abs[pid] 进程组中的任意进程结束

status:输出型参数,接收结束状态码

options:

​ WNOHANG 非阻塞模式,如果当前没有子进程结束,则立即返回0

​ WUNTRACED 如果有子进程处于暂停态,返回该进程的状态

​ WCONTINUED 如果 有子进程从暂停态转为继续运行,返回该子进程的状态

WIFEXITED(status)

​ 判断进程是否是正常结束,如果是返回真

WEXITSTATUS(status)

​ 如果进程是正常结束的,可以获取到正确的结束状态码

WIFSIGNALED(status)

​ 判断进程是否异常结束,如果是返回真

WTERMSIG(status)

​ 如果进程是异常结束的,可以获取到杀死进程的信号

WIFSTOPPED(status)

​ 判断子进程是否转为暂停态,是返回真

WSTOPSIG(status)

​ 获取导致子进程进入暂停态的信号

WIFCONTINUED(status)

​ 判断子进程是否由暂停转为继续,是返回真

int system(const char *command);

功能:通过创建子进程去执行一个可执行文件

返回值:子进程结束后才返回

注意:该函数底层调用了fork、vfork、exec函数、wait函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值