1.进程创建
利用fork函数,在Linux中fork函数是一个非常重要的函数,它从已存在的进程中创建一个新进程,新进程为子进程而原进程为父进程。当进程调用fork函数,控制转移到内核中的fork代码后,内核:
1.分配新的内存块和内存数据结构给子进程
2.将父进程部分数据结构内容拷贝给子进程
3.添加子进程到系统进程列表中
4.fork返回,调度器开始调度
当一个进程调用fork后,就会有两个二进制代码相同的进程,但是每个进程又可以做自己的事情。
来一段代码
#include<stdio.h>
int main()
{
pid_t pid=fork();
int x=1;
if(pid==0)
{
printf("child:x=%d\n",++x);
exit(0);
}
printf("parent:x=%d\n",--x);
exit(0);
}
当我们在Linux下运行此代码,得到结果
parent:x=0
child:x=2
由此我们不难看出子进程和父进程之间:
1.并发执行:父进程和子进程是并发运行的独立进程,内核能够以任意方式交替执行他们逻辑的控制流中的指令
2.俩个独立的地址空间:不难看出,x的初始值是1。但是,父进程和子进程是独立的进程。他们都有自己的私有地址空间,所以父进程和子进程对x所做的任何改变都是独立的,不会反映在另一个进程的内存中。
但是通常,父子 进程的代码是共享的,父进程不再写入时,数据也是共享的,当任意一方试图写入,便以写时拷贝的方式各自拷贝一份
如图
在经行写操作前数据段和代码段都是共享内存页,但是当一个开始修改操作,数据段便会拷贝出新的内存页。
vfork函数
vfork函数也是用来创建子进程但是vfork函数创建的子进程与父进程共享地址空间
vfork保证了子进程先运行,在它调用了exec或exit之后父进程才能被调度运行。
2.进程终止
进程常见的退出方法:
正常退出:
1.从main返回
2.调用exit
3._exit
异常退出:
ctrl + c,信号终止
exit函数,在调用exit前做了这些工作:
1.用户通过atexit或on_exit定义的清理函数
2.关闭打开流,所有的缓存数据均被写入
3.调用_exit
return 退出
return是一种更常见的退出方法执行return n等同于执行exit(n),应为调用main的运行时函数会将main的返回值当做exit的参数