当前位置:   article > 正文

头歌(Linux之进程管理一):第3关:进程创建操作-vfork_头歌linux之进程等待

头歌linux之进程等待

任务描述

在上一关我们学习使用fork函数创建新进程,本关我们将介绍如何另一种创建新进程的系统调用函数。

本关任务:学会使用C语言在Linux系统中使用vfork系统调用创建一个新的进程。

相关知识

在上一关卡中,我们介绍了fork的使用方法。使用fork创建的子进程的特点是:(1)子进程采用写时复制(COW)技术来为子进程创建地址空间;(2)子进程和父进程的执行顺序是由操作系统调度器来决定的。

本关将介绍Linux系统中另一个创建进程的系统调用函数vforkvfork函数是一个历史遗留产物。vfork创建进程与fork创建的进程主要有一下几点区别:

  1. vfork创建的子进程与父进程共享所有的地址空间,而fork创建的子进程是采用COW技术为子进程创建地址空间;
  2. vfork会使得父进程被挂起,直到子进程正确退出后父进程才会被继续执行,而fork创建的子进程与父进程的执行顺序是由操作系统调度来决定。

vfork性能要比fork高,主要原因是vfork没有进行所有数据的复制,尽管fork采用了COW技术优化性能,但是也会为子进程的页表项进行复制,因此vfork要比fork快。

使用vfork时要注意,在子进程中对共享变量的修改也会影响到父进程,因此vfork在带来高性能的同时,也使得整个程序容易出错,因此,开发人员在使用vfork创建进程时,一定要注意对共享数据的修改。

由于vfork创建的子进程和父进程共享所有的数据(栈、堆等等),因此,采用vfork创建的子进程必须使用exit或者exec函数族(下一关将介绍这些函数的功能)来正常退出,不能使用return来退出。

exit函数是用来结束正在运行的整个程序,exit是系统调用级别,它表示一个进程的结束;而return 是语言级别的,它表示调用堆栈的返回。

vfork函数是系统调用函数,man 2 vfork来查看其使用方法。而exit函数是库函数,因此使用man 3 exit来查看其使用方法。

使用vfork函数创建进程

vfork函数的具体的说明如下:

  • 需要的头文件如下:

    1. #include <sys/types.h>
    2. #include <unistd.h>
  • 函数格式如下: pid_t vfork(void);

  • 函数返回值说明: 调用成功,vfork函数两个值,分别是0和子进程ID号。当调用失败时,返回-1,并设置错误编号errno

注意:vfork函数调用将执行两次返回,它将从父进程和子进程中分别返回。从父进程返回时的返回值为子进程的 PID,,而从子进程返回时的返回值为0,并且返回都将执行vfork之后的语句。vfork创建的子进程必须调用exit函数来退出子进程。

案例演示1: 编写一个程序,使用vfork函数创建一个新进程,并在子进程中打印出其进程ID和父进程ID,在父进程中返回进程ID。详细代码如下所示:

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <unistd.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <errno.h>
  7. int main()
  8. {
  9. pid_t pid;
  10. pid = vfork();
  11. if(pid == -1)
  12. {
  13. //创建进程失败
  14. printf("创建进程失败(%s)!\n", strerror(errno));
  15. return -1;
  16. }
  17. else if(pid == 0)
  18. {
  19. //子进程
  20. sleep(2); //睡眠2秒
  21. printf("当前进程为子进程:pid(%d),ppid(%d)\n", getpid(), getppid());
  22. }
  23. else
  24. {
  25. //父进程
  26. printf("当前进程为父进程:pid(%d),ppid(%d)\n", getpid(), getppid());
  27. }
  28. //子进程和父进程分别会执行的内容
  29. exit(0);
  30. }

将以上代码保存为vforkProcess.c文件,编译执行。可以看到vforkProcess创建的子进程尽管使用sleep函数睡眠了2秒,但是函数父进程的执行顺序在子进程后,这就是vfork的特性。

当我们将以上代码中的exit(0)换成return 0时,则会出现如下错误。

出现以上错误的原因是当子进程使用return退出时,操作系统也会把栈清空,那么当父进程继续使用return退出时,则会发现栈已经被清空了,这就相当于free两次同一块内存,因此会出现错误。

编程要求

本关的编程任务是补全右侧代码片段中BeginEnd中间的代码,具体要求如下:

  • 补全createProcess函数,使用vfork函数创建进程,并在子进程中输出"Children"字符串(提示:需要换行),在父进程中输出"Parent"字符串(提示:需要换行)。

测试说明

本关的测试需要用户在右侧代码页中补全代码,然后点击评测按钮,平台会自动验证用户是否按照要求去检测结果。

  1. #include <unistd.h>
  2. #include <sys/types.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <errno.h>
  6. #include <stdlib.h>
  7. /************************
  8. * 提示: 不要在子进程中使用return来退出程序
  9. *************************/
  10. void createProcess()
  11. {
  12. /********** BEGIN **********/
  13. pid_t pid=vfork();
  14. if(pid==-1)
  15. {
  16. printf("创建进程失败(%s)!\n", strerror(errno));
  17. }
  18. else if(!pid)
  19. {
  20. sleep(2);
  21. printf("Children\n",getpid(),getppid());
  22. }
  23. else
  24. {
  25. printf("Parent\n",getpid(),getppid());
  26. }
  27. /********** END **********/
  28. exit(0);
  29. }

 第四关链接--头歌(Linux之进程管理一):第4关:进程终止_小妞无语的博客-CSDN博客

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/813120
推荐阅读
相关标签
  

闽ICP备14008679号