当前位置:   article > 正文

[linux]进程控制——进程创建

[linux]进程控制——进程创建

一、fork:

linux中fork函数从已存在进程中,创建一个新进程。新进程为子进程,而原进程为父进程。

返回值:子进程中返回0,父进程返回子进程id,出错返回-1。

1、常规用法:

一个父进程希望复制自己,使父子进程同时执行不同的代码段。例如,父进程等待客户端请求,生成子进程来处理请求。
一个进程要执行一个不同的程序。例如子进程从fork返回后,调用exec函数。

进程调用fork,当控制转移到内核中的fork代码后,内核执行以下内容:

  • 分配新的内存块和内核数据结构给子进程
  • 将父进程部分数据结构内容拷贝至子进程
  • 添加子进程到系统进程列表当中
  • fork返回,开始调度器调度

当一个进程调用fork之后,就有两个二进制代码相同的进程。而且它们都运行到相同的地方。

fork之前父进程独立执行,fork之后,父子两个执行流分别执行。注意,fork之后,谁先执行完全由调度器决定。 

2、写时拷贝:

通常,父子代码共享,父子都不写入时,数据也是共享的,当任意一方试图写入,便以写时拷贝(重新申请空间,进行拷贝,修改页表)的方式各自一份副本。

注:

父进程创建子进程的时候首先将自己的读写权限改成只读,然后再创建子进程。

当用户对某一批数据进行写入时,页表转换会因为权限问题而出错。此时操作系统就可以介入:

1、真的出错了(如越界(尝试写入代码区等))

2、不是出错,触发:重新申请内存,拷贝内容的策略机制(写时拷贝)

二、补充:makefile文件

  1. 1 cc=gcc
  2. 2 src=test.c
  3. 3 target=mybin
  4. 4
  5. 5 $(target):$(src)
  6. 6 gcc $^ -o $@ -g #加上-g表示以debug模式编译该程序
  7. 7 .PHONY:clean
  8. 8 clean:
  9. 9 rm -f $(target)
  10. 10

三、以模拟孤儿进程为例:

(以下包含进程创建)

  1. 1 #include<stdio.h>
  2. 2 #include<unistd.h>
  3. 3 #include<stdlib.h>
  4. 4
  5. 5 //模拟孤儿进程
  6. 6 int main()
  7. 7 {
  8. 8 pid_t id = fork();
  9. 9
  10. 10 if(id < 0)
  11. 11 {
  12. 12 return 1;
  13. 13 }
  14. 14 else if(id > 0)
  15. 15 {
  16. 16 int cnt = 5;
  17. 17 while(cnt)
  18. 18 {
  19. 19 printf("这是父进程,运行时间:%d\n",cnt--);
  20. 20 sleep(1);
  21. 21
  22. 22 }
  23. 23 printf("父进程dead!:%d\n",cnt--);
  24. 24 exit(2);
  25. 25 }
  26. 26 else
  27. 27 {
  28. 28 while(1)
  29. 29 {
  30. 30 printf("这是子进程,持续运行\n");
  31. 31 sleep(1);
  32. 32 }
  33. 33
  34. 34
  35. 35 }
  36. 36
  37. 37
  38. 38 return 0;
  39. 39 }
  40. 40

四、监视:

执行以下命令:

未执行该模拟孤儿进程的程序时:

执行该模拟孤儿进程的程序:

父进程未退出时:

 可以看出父、子进程皆在运行,父进程PID是15379,子进程PID是15380,子进程的PPID是15379。

父进程退出后: 

可以看出,父进程已经不在运行,只有子进程在运行。此时,子进程的PPID不再是它原来父进程的 PID,而是变为了1。(这种情况可以理解为托孤)

此时如果我们不想让该进程继续运行,我们可以通过 kill -9 15380 终止该子进程。

五、创建多进程

1、myprocess.c

  1. #include<stdio.h>
  2. #include<sys/types.h>
  3. #include<unistd.h>
  4. #include<stdlib.h>
  5. #define N 10
  6. void worker()
  7. {
  8. int cnt = 10;
  9. while(cnt)
  10. {
  11. printf("我是子进程,pid: %d, ppid:%d ,cnt: %d\n", getpid(),getppid(), cnt);
  12. sleep(1);
  13. cnt--;
  14. }
  15. }
  16. typedef void (*call_back_t)();
  17. void createSubProcess(int n ,call_back_t cb)
  18. {
  19. int i = 0;
  20. for(i = 0; i < n; i++)
  21. {
  22. sleep(1);
  23. pid_t id = fork();
  24. if(id == 0)
  25. {
  26. printf("创建子进程:%d\n", i);
  27. cb();
  28. exit(0);
  29. }
  30. }
  31. }
  32. int main()
  33. {
  34. createSubProcess(N, worker);
  35. sleep(100);
  36. return 0;
  37. }

2、运行myprocess.c

 

 

3、监视

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

闽ICP备14008679号