基于toyix的进程和轻权进程的学习(4)

我们可以看到这两个进程的代码段并不一样,所以它们的代码段不是共享的。所以fork函数创建的两个进程的代码段、数据段、栈段都是不共享的。而且我们注意到父进程是先打印的,也就是说父进程是先执行的,在父进程执行后子进程并没有被撤销。

那么frk函数和fork函数有什么区别呢?由函数手册可知,frk函数也是创建一个与父进程相同的子进程,而它的不同之处是这两个进程是共享数据段的,而且如果父进程结束了,子进程也会被撤销。

我们将上面的函数里的fork函数改成frk函数来执行:

第一个程序修改如下,这里在a++后面调用delay函数是为了在父进程a++执行完后,子进程有足够的时间去完成a++操作,如果父进程的a++执行后就执行下面的打印语句,子进程可能还没有执行a++,那么可能的结果就是父进程打印出来的a的值为1,子进程打印出来的值为2

基于toyix的进程和轻权进程的学习

执行结果如下:

这里打印出来a的值都为2,说明了这两个进程是共享数据段的。

我们把第二个程序修改为如下:

基于toyix的进程和轻权进程的学习

这里程序最后的delay100)的作用也是让父进程暂停等待子进程执行,否则父进程结束后会撤销子进程,那么子进程的打印语句就无法执行。

执行结果如下:

这里的打印出来的两个函数的代码段地址不同,所以frk创建的子进程也不与父进程共享代码段。我们注意到子进程打印出来的地址是一个错误的地址,因为我们是用十六进制打印的地址,而r是不属于十六进制的数的,如果用十进制打印,结果如下:

这个地址应该是正确地地址,那么为什么用十六进制打印会出现错误的地址呢?按理说%x不应该输出大于f的值,那么我觉得可能是这里printf里对%x的实现有问题。

如果上面的程序最后不加delay100),执行结果如下:

因为父进程在执行完后撤销了子进程,所以只有父进程执行了printf函数。

所以我们得到的结论是frk函数创建的子进程与父进程共享数据段,不共享代码段和栈段。

我们之前在讨论进程的三态模型时发现在正常情况下,进程是从运行态退出的,但是frk函数创建的子进程可能没有执行完就因为父进程的结束而被撤销了,这是为什么呢?查询资料发现,实际上还存在从就绪态或者阻塞态到结束状态的释放转换。进程的退出可以分为正常退出和异常退出,异常退出的原因包括进程执行超时、内存不足、非法指令或地址访问、I/O操作失败、被其他进程所终止等,比如父进程可以在任何时间终止子进程,只是fork中设置的是父进程退出不撤销子进程,而frk中设置的是父进程结束时撤销子进程,我们也可以写一个函数创建子进程,并在父进程执行时就撤销它。

那么为什么fork函数和frk函数的功能差不多,但是一个共享数据段、一个不共享数据段呢?我们知道进程包含数据段,而fork创建的子进程不与父进程共享数据段,所以在创建时系统要把父进程数据段的内容复制到子进程的数据段中,这会造成一定的开销,而且也不利于父子进程间交换数据,所以forkfrk创建的进程各有特点。为了区别fork创建的进程,我们把frk创建的进程叫做轻权进程。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/26974be0ecc82c69b54cff0f7be50720.html