wait和waitpid
#include
#include
pid_t wait(int * status);
pid_t waitpid(pid_t pid, int *status, int options);
1、获取子进程status
- wait和waitpid都有status参数,是一个输出型参数
- 传值NULL表示不关心子进程退出状态信息
- 操作系统会根据该参数将子进程退出信息反馈给父进程
研究status低16比特位:
- 正常终止:8位退出状态 + 8位零
- 被信号所杀:8位未用 + core dump标志 + 终止信号
#include
#include
#include
#include
#includeusing namespace std;int main()
{pid_t pid &#61; fork();if(pid &#61;&#61; -1){perror("error");exit(1);}if(pid &#61;&#61; 0){sleep(20);exit(8);}else{int status;int ret &#61; wait(&status);if(ret > 0 && (status & 0x7F) &#61;&#61; 0){cout<<"child exit code:"<<((status>>8) & (0xFF))<<endl;}else if(ret > 0){cout<<"sig code:"<<((status) & (0x7F))<<endl;}}return 0;
}
第一次运行什么都不做&#xff0c;程序正常退出&#xff0c;返回退出状态码&#xff1b;
第二次运行时&#xff0c;打开另一个终端&#xff0c;找到子进程id&#xff0c;kill掉&#xff0c;程序异常退出&#xff0c;返回终止信号码&#xff1b;
进程的阻塞等待方式
#include
#include
#include
#include
#include
#includeusing namespace std;int main()
{pid_t pid &#61; fork();if(pid &#61;&#61; -1){perror("error");exit(1);}if(pid &#61;&#61; 0){cout<<"child pid:"<<getpid()<<endl;sleep(5);exit(257);}else{int status &#61; 0;pid_t ret &#61; waitpid(-1, &status, 0);if(WIFEXITED(status) && (ret &#61;&#61; pid)){cout<<"child exit code:"<<WEXITSTATUS(status)<<endl;}else{cout<<"failed"<<endl;exit(1);}}return 0;
}
2、进程程序替换
替换原理
- 用fork创建子进程后执行的是和父进程相同的程序&#xff0c;有可能执行不同的代码分支
- 子进程往往要调用一种exec函数以执行另一个程序
- 当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行
- 调用exec并不创建新进程,所以调用exec前后该进程的id并未改变
替换函数
只有execve是真正的系统调用&#xff0c;上面几个最终调用execve
函数解释
- 调用成功则加载新程序开始执行&#xff0c;不再返回
- 调用出错返回-1
命名解释
- l(list)&#xff1a;参数采用列表
- v(vector)&#xff1a;参数采用数组
- p(path)&#xff1a;自动搜索环境变量PATH
- e(env)&#xff1a;自己维护环境变量
举例
#includeint main()
{char *const argv[] &#61; {"ps", "-ef", NULL};char *const envp[] &#61; {"PATH&#61;/bin:/usr/bin", "TERM&#61;console", NULL};execl("/bin/ps", "ps", "-ef", NULL);execlp("ps", "ps", "-ef", NULL);execle("ps", "ps", "-ef", NULL, envp);execv("/bin/ps", argv);execvp("ps", argv);execve("/bin/ps", argv, envp);return 0;
}
调用exec
执行ls -l
指令
#includeint main()
{char *const argv[] &#61; {"ls","-l",NULL};char *const envp[] &#61; {"PATH&#61;/bin:/usr/bin","TERM&#61;console",NULL};execve("/bin/ls",argv,envp);return 0;
}