进程的创建也是操作系统所要做的工作,当我们执行一个程序时,操作系统就会创建与这个程序完成相关的进程,不需要我们手动创建。我们可以用get_pid函数得到调用进程的进程号:
用do 1执行程序,结果如下:
发现结果进程的序列号为1,在进程就绪状态进程监视器显示的进程号也为1。
我们再用do 1 1 1执行三个进程:
可以看到程序创建了三个进程,它们的进程号分别为1、2、3.
也就是说,这里进程号是从1开始连续分配的,每执行一次程序就创建一个进程,那么一个程序可以创建开启多个进程吗?我们可以使用fork函数和frk函数来创建多个进程。
Fork函数的作用是创建一个与父进程相同的子进程:
执行结果为:
Fork创建了一个子进程,所以打印出了2个进程号。我们把创建新进程前的进程叫做父进程,把创建新进程后的进程叫做子进程,那么这两个进程哪个是父进程,哪个是子进程呢?我们是无法通过它们的进程号来区分的,但是我们知道fork函数在创建进程成功后,在父进程中会返回子进程的进程号,在子进程中会返回0,也就是说,在父进程中fork()的值是一个非0值,而在子进程中,fork()的值为0.那么我们可以通过判断fork()的值是否为0来判断这个进程是父进程还是子进程:
执行结果如下:
有程序的执行结果可知,进程1是父进程,进程2是子进程。
Fork函数有两个特点:1、父子进程不共享数据段。2、父进程结束后不撤销子进程。
什么是数据段呢?进程是程序的执行过程,它的执行需要调用程序里设置的数据来给cpu进行计算得到需要的结果,这些程序里设置的数据就存储在一段存储空间里,这个空间就叫做这个进程的数据段,它是进程所需资源的一种,是在创建进程时由操作系统分配给进程的。
进程一般由控制信息和本体信息组成,进程号就属于进程的控制信息,本体信息一般是由代码段、数据段、栈段所组成。栈段是用来保存如cpu现场等进程的特有信息,我们知道局部变量就是用栈段存储的,比如上面的变量i,它在父子进程中的值是不同的,所以我们可以知道栈段是不可能被父子进程共享的。我们知道全局变量是存放在数据段里的,要验证数据段是否共享,我们可以对全局变量进行操作和打印:
执行结果为:
所以这里打印的a的值都为1,而如果两个进程共享一个数据段,那么a会自加2次,输出的结果应该为2。所以这里的两个进程没有共享数据段。
要判断两个进程的代码段是否共享,只需要看看它们代码段的地址是否相同即可,我们打印这两个进程的地址:
执行结果如下: