Linux----进程控制(下)
Posted 4nc414g0n
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux----进程控制(下)相关的知识,希望对你有一定的参考价值。
Linux----进程控制(下)
3)进程等待
进程等待的意义:
- 回收僵尸进程(解决内存泄漏)
- 需要获取子进程的运行结束状态(不是必要)
- 父进程晚于子进程退出,可以规范化进行资源回收(编码)
wait()
#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int*status);
返回
:等待任意一个子进程,当子进程退出,wait就可以返回,成功返回被等待进程pid,失败返回-1
int*status
:输出型参数,获取子进程退出状态,不关心则可以设置成为NULL
例:
int main() pid_t id=fork(); if(id<0) perror("fork"); return 1; else if(id==0) int count=5; while(count--) printf("child running: %d,pid:%d,ppid:%d\\n",count,getpid(),getppid()); sleep(1); printf("child quit...\\n"); exit(0); else printf("father is waiting...\\n"); sleep(10);//让子进程维持5s的z状态 pid_t ret=wait(NULL); printf("father wait done,ret is: %d\\n",ret); return 0;
shell监测脚本:
while :; do echo "==================================="; ps ajx | grep test1 | grep -v grep; echo "==================================="; sleep 1; done
waitpid()
#include <sys/wait.h>
pid_ t waitpid(pid_t pid, int *status, int options);
返回:
- 当正常返回的时候waitpid返回收集到的子进程的进程ID
- 如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0
- 如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在
pid:
- pid=(pid_t)-1,等待任一个子进程,与wait()等效
- pid>0,等待其进程ID与pid相等的子进程(等待指定的子进程:fork返回给父进程)
- pid=0,则请求其进程 组 ID 等于调用进程的任何子进程的状态(略)
- pid<(pid_t)-1,则为进程 组 ID 等于 pid 绝对值的任何子进程请求状态(略)
status:
- WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
- WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)
options:
- WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进程的ID
例:
int main() pid_t id=fork(); if(id<0) perror("fork"); return 1; else if(id==0) int count=5; while(count--) printf("child running: %d,pid:%d,ppid:%d\\n",count,getpid(),getppid()); sleep(1); printf("child quit...\\n"); exit(121); else printf("father is waiting...\\n"); sleep(10);//让子进程维持5s的z状态 int status=0; pid_t ret=waitpid(-1,&status,0); int code = (status>>8)& 0xFF; printf("father wait done,ret is the pid of child process: %d\\n",ret); printf("The code is: %d\\n",code); if(code==0) printf("success\\n"); else printf("wrong\\n"); return 0;
①status
wait和waitpid都有一个status参数
int status共32位,下图是低16位
当子进程正常终止时用(status>>8)& 0xFF
可以得到退出状态(不会收到任何信号)
当子进程异常终止(收到OS发送的信号),同时带有一位的core dump标志位,用status & 0x7F
可以获得
例如下面由于段错误子进程终止:
两个
宏函数WIFEXITED和WEXITSTATUS
可以用来判断子进程退出状态(正常/异常终止)if(WIFEXITED(status)) printf("quit normal\\n"); printf("quit code is: %d\\n",WEXITSTATUS(status)); else printf("process quit error\\n");
问1:为什么不设置一个全局变量code,而要返回退出码?
答
:写时拷贝,子进程不能更改code
问2:waitpid从哪里拿到的status值的?子进程已经退出了
答
:子进程处于Z(僵尸状态),有内存泄漏(还有数据),waitpid从task_struct中获得的
下面是linux-2.6.39的源码 (进程退出码最终会被写入到exit_code里)
②option(阻塞与非阻塞)
如果option选项传入的是
WNOHANG
就是非阻塞
等待方式,如果option传的是0
默认是阻塞
的
非阻塞:
这里一共有三种返回状态:
- 失败返回(下一次再检测)
- 失败返回(真正的失败)
- 成功返回
阻塞等待理解:
阻塞等待:父进程等待,子进程运行
- 这里的“
等待
”:指OS把父进程放入等待队列,并将进程状态设置为非R状态- 子进程运行完了再唤醒父进程,将父进程从等待队列中取出,放入运行队列,同时将其设为R状态
4)进程程序替换
进程程序替换
:
- 通过exec系列函数,让特定进程去加载磁盘中的其他程序,已达到运行的目的,期间不创建新的进程
为什么要进程程序替换:
- 子进程执行父进程的一部分代码
- 子进程自身新的程序需求
替换函数
头文件:
#include <unistd.h>
返回:
- 如果调用成功则加载新的程序从启动代码开始执行,不再返回
- 如果调用出错则返回-1
只有execve是真正的系统调用,其它五个函数最终都调用 execve,这些函数之间的关系如下图:
①execl系列(l:list)
int execl(const char *path, const char *arg, ...);
path
:执行的程序(带路径)
arg...
:给执行程序传递的参数(…是可变参数)必须以NULL结尾
int execlp(const char *file, const char *arg, ...);
file
:执行的程序(不带路径,会自动到环境变量找)
arg...
:给执行程序传递的参数(…是可变参数)必须以NULL结尾
int execle(const char *path, const char *arg, ...,char *const envp[]);
path
:执行的程序(带路径)
arg...
:给执行程序传递的参数(…是可变参数)必须以NULL结尾
envp
:传入默认的或者自定义的环境变量给目标可执行程序
②execv系列(v:vector)
int execv(const char *path, char *const argv[]);
path
:执行的程序(带路径)
arg[]
:给执行程序传递的参数(与execl系列区别就是将参数放入了一个数组)必须以NULL结尾
int execvp(const char *file, char *const argv[]);
file
:执行的程序(不带路径,会自动到环境变量找)
arg[]
:给执行程序传递的参数(与execl系列区别就是将参数放入了一个数组)必须以NULL结尾
int execve(const char *path, char *const argv[], char *const envp[]);
path
:执行的程序(带路径)
arg[]
:给执行程序传递的参数(与execl系列区别就是将参数放入了一个数组)必须以NULL结尾
envp[]
:传入默认的或者自定义的环境变量给目标可执行程序
int execvpe(const char *file, char *const argv[], char *const envp[]);
file
:执行的程序(不带路径,会自动到环境变量找)
arg[]
:给执行程序传递的参数(与execl系列区别就是将参数放入了一个数组)必须以NULL结尾
envp[]
:传入默认的或者自定义的环境变量给目标可执行程序
场景
shell解释器fork()创建子进程执行命令
Linux----50行简易shell
以上是关于Linux----进程控制(下)的主要内容,如果未能解决你的问题,请参考以下文章