多进程
1. 多进程相关的理论概念
进程:一个正在运行的程序,系统中就会产生一个对应的进程,动态的概念,在内存中运行
程序:编译器编译得到的二进制程序,静态的概念,存储在电脑的磁盘上
父进程:你调用fork这个函数,创建出来的就是子进程,调用fork的进程就是父进程
子进程:fork产生的都是子进程
进程的ID号(pid):类似于进程的"身份证号"
相关的命令:
ps -elf
查看当前系统进程的运行状态(PID --》进程ID号 CMD --》进程的名字)
cpu的调度策略:
孤儿进程(僵尸进程): 父进程先于子进程退出,导致子进程的资源没有人回收,子进程就变成孤儿进程
新版本的ubuntu,孤儿进程会被系统中一个叫做init的进程回收
进程的组成: 栈,堆,数据段,代码段,进程控制块(PCB--》process contrl block)
进程控制块: 指的是系统中定义的一个结构体,该结构体用于存储进程运行时候的状态信息
struct task_struct
{
pid_t pid; //当前进程的ID
struct files_struct *files;
//指向另外一个结构体数组的,这个数组专门用来存放你的程序中已经打开的文件信息
};
进程组:多个进程组成的一个集合
2. linux提供的跟进程有关的接口函数
(1)进程的创建
pid_t fork(void);
返回值: >0 父进程,此时返回值中保存的就是创建成功的那个子进程的ID号
==0 子进程
<0 失败
特点(重点):一次调用两次返回,跟我们以前学习的函数是不一样,我们以前的函数都只能一次调用,返回一次
父子进程究竟谁先执行,谁后执行,是不确定的
(2)进程的退出和回收
退出进程:
void exit(int status);
void _exit(int status);
参数:表示进程的退出值
跟return的区别
return是关键字,exit和_exit都是函数
exit和_exit的区别
exit结束进程的时候,会刷新缓冲区,但是_exit不会
刷新缓冲区:
遇到回车,或者return或者exit()都能刷新缓冲区
(3)进程的回收
#include <sys/wait.h>
特点: 阻塞等待当前父进程,直到子进程退出为止
pid_t wait(int *wstatus);
返回值:成功 返回回收的那个子进程的ID号
失败 -1
参数:wstatus --》用于保存进程退出时候的状态信息(包括退出值,)
注意:exit的退出值仅仅只是退出状态信息的一部分
pid_t waitpid(pid_t pid, int *wstatus, int options);
返回值:成功 返回回收的那个子进程的ID号
失败 -1
参数:pid --》waitpid(-10002, ); 我要回收进程组ID是10002里面的某个进程
waitpid(-1,); 我要回收任意一个子进程
waitpid(0,); 我要回收本组中的任意一个子进程
waitpid(20000,); 我要指定回收ID号是20000的进程
options --》WNOHANG
非阻塞等待(父进程退出的时候,如果子进程还没有结束,那么父进程不会阻塞等待子进程,父进程会直接退出)
0 阻塞等待
(4)获取当前进程的ID号,获取父进程的ID号
pid_t getpid(void);
返回值:当前进程的ID号
pid_t getppid(void);
返回值:当前进程的父进程的ID号
pid_t getpgrp(void);
返回值:当前进程所属进程组的ID号
3. 在一个进程中调用执行另外一个进程
在一个进程中调用执行shell命令
两种实现方法:
(1)方法一: system()
eg:system("madplay /1.mp3");
(2)方法二: exec函数族
底层原理:这六个函数通过创建子进程,然后在子进程里面执行你的命令或者程序
int execl(const char *path, const char *arg, ...);
返回值:失败 -1
参数:path --》你要执行的程序或者命令的路径名
arg --》你要执行的程序或者命令的参数
int execlp(const char *file, const char *arg, ...);
参数:file --》你要执行的程序或命令的名字(不需要写路径名)
arg --》你要执行的程序或者命令的参数(以列表的形式逐一列举)
int execle(const char *path, const char *arg, ... (char *) NULL, char * const envp[]);
参数:path --》你要执行的程序或者命令的路径名
arg --》你要执行的程序或者命令的参数
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[]);
l ---》参数必须以列表的形式逐一列举
p ---》会去系统的环境变量中查找要执行的命令或程序,只需要写程序的名字即可
e ---》可以设置环境变量
v ---》参数用指针数组存放
echo $PATH //打印系统的环境变量PATH的值