进程创建
fork函数
fork函数从已存在的进程中创建一个新进程。新进程为子进程,原进程为父进程。
#include <unistd.h>
pid_t fork(void);
- fork函数返回值:父进程返回子进程的pid,子进程返回0,出错返回-1。
- 进程调用fork,当控制转移到内核中fork代码之后,内核会分配新的内存块和内核数据结构给子进程,将父进程部分数据结构内容拷贝至子进程,添加子进程到系统进程列表中,fork返回,开始调度器调度。
- 写时拷贝,通常,父子代码共享,父子在不写入时,数据也共享,但任意一方试图写入,便以写实拷贝的方法各自私有一份。
1 #include <iostream>
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include <sys/types.h>
5 using namespace std;
6
7 int main()
8 {
9 pid_t id = fork();
10 if(id < 0){
11 cerr << "fork error" << endl;
12 }
13 else if(id == 0){
14 cout << "i am a child!" << endl;
15 exit(1);
16 }
17 else{
18 cout << "i am parent!" << endl;
19 sleep(2);
20 }
21 return 0;
22 }
进程终止
进程退出场景
- 代码跑完,结果正确
- 代码跑完,结果不正确
- 代码没跑完,异常终止
进程常见退出方法
echo $? //查一个进程退出时的退出码
1.正常终止
(1) 从main返回(main函数返回值=当前进程退出码)
(2) 调用exit(任何地方调用exit,都表示当前进程退出)
#include <unistd>
void exit(int status)
- exit最后也会调用exit,但在调用之前,执行用户通过aexit或on_exit的清理函数;然后冲刷缓冲,关闭流等。
(3) _exit(直接终止进程,之前的数据不要了)
#include <unistd.h>
void _exit(int status);
- status定义了进程的终止状态,父进程通过wait获取
- status仅有低8位可以被父进程所用。如_exit(-1)的返回值是255。
2.异常退出
- ctrl + c,信号终止
3.return退出
- return是一种常见的退出进程方法,执行return n等同于执行exit(n),因为调用main函数的运行时函数会将main的返回值当做exit的参数。
进程等待
wait方法
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int* status)
- 返回值:成功返回被等待进程的pid,失败返回-1。
- 参数:输出型参数,获取子进程退出状态,不关心则设为NULL。
waitpid方法
pid_t waitpid(pid_t pid, int* status, int options)
- 返回值:正常返回收集到的子进程的进程id;如果设置了WNOHANG,调用的waitpid发现没有已退出的子进程,返回0;出错返回-1。
- pid = -1,等待任一子进程,与wait等效;pid > 0, 等待起进程id与pid相等的子进程。
- WIFEXITED(status):退出信号。
- WEXITSTATUS(status):退出码。
- options:wait等待的方式有两种,一种是阻塞方式,一种是非阻塞方式。
- 如果子进程已经退出,调用wait/waitpid时,wait/waitpid会立即返回,并且释放资源,获得子进程退出信息。
- 如果在任意时刻调用wait/waitpid,子进程且正常运行,进程可能阻塞。
如果不存在该子进程,则立即返回出错。
具体代码实现:
进程的阻塞等待方式:
#include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <sys/types.h>
5 #include <sys/wait.h>
6
7 int main()
8 {
9 pid_t id = fork();
10 if(id < 0)
11 {
12 printf("fork error\n");
13 }
14 else if(id == 0)
15 {
16 printf("child is runnning..., pid : %d\n", getpid());
17 sleep(5);
18 exit(13);
19 }
20 else
21 {
22 printf("parent is running..., ppid : %d\n", getppid());
23 int status = 0;
24 pid_t ret = waitpid(-1, &status, 0);
25 if(ret < 0)
26 {
27 printf("wait error\n");
28 }
29 else
30 {
31 printf("success!\n");
32 sleep(5);
33 }
34 }
35 return 0;
36 }