本片博客的操作均在Linux系统下进行:
1. 进程创建
进程创建:父进程来创建除一个新的子进程的过程。
创建进程的方法-------fork()函数和vfork()函数
父进程想要创建一个函数就需要使用fork()函数或者vfork()函数。
- fork()函数;
//头文件 #include <unistd.h>
//fork()函数原型: pid_t fork(void);
//返回值: 从进程中返回0,父进程返回子进程id,出错返回-1;
- vfork()函数;
//头文件: #incldue <unistd.h>
//vfork()函数原型: pid_t vfork(void);
//返回值: 从子进程中返回0,父进程返回子进程id,出错返回-1;
fork()v函数和fork()函数的使用方法相同;常用fork() 函数来创建新进程;
#include<stdio.h>
#include<unistd.h>
int main()
{
pid_t id = fork();
if(id < 0)
perror("fork failed\n");
else if(id == 0)
{
printf("子进程\n");
return 0;
}
else
{
printf("父进程\n");
}
return 0;
}
在父进程调用fork()函数之后,内核会进行如下操作来创建新进程:
- 分配新的内存块和内核数据结构给子进程;
- 将父进程调用fork()函数之后的代码和数据拷贝给子进程;
- 添加子进程到系统进程列表中;
- fork返回,开始调度调度器;
注意:父子进程之间代码共享;父子进程不再写入时,数据也是共享的,当任意一方试图写入时,便会以写时拷贝的方式各自私有一份数据;
2. 进程终止
进程退出的三种场景:
- 代码运行结束,结果正确;
- 代码运行结束,结果不正确;
- 代码异常退出;
进程异常退出的本质:进程收到了操作系统发来的信号;
进程退出的常见方法:
- 正常退出:
从main函数中退出;
调用exit()退出;
调用_exit()退出;
这三种退出方法的异同:
- 一般从main函数中退出都是使用return 退出的,在main函数中使用return n退出等同于执行exit(n)退出,main的运行时函数会将main的返回值当做exit的参数;
- exit()函数退出的最后,也会调用_exit(),但调用exit()退出和调用_exit()退出的不同就是exit函数在调用_exit()会执行做一些工作(执行用户通过 atexit或on_exit定义的清理函数;关闭所有打开的流,所有的缓存数据均被写入);所以,直观上看来就是,调用exit()函数退出有可能会比调用_exit()函数退出多显示一些内容;
//调用_exit()退出
#include<unistd.h>
#include<stdio.h>
int main()
{
printf("_exit()");
_exit();
}
//调用exit()退出
#include<unistd.h>
#include<stdio.h>
int main()
{
printf("exit()");
_exit();
}
- 异常退出:
进程在运行时,按下Ctrl+c,进程被强制退出;