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

一、fork:

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

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

1、常规用法:

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

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

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

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

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

2、写时拷贝:

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

注:

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

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

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

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

二、补充:makefile文件

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

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

(以下包含进程创建)

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 
  5 //模拟孤儿进程
  6 int main()
  7 {
  8   pid_t id = fork();
  9 

 10   if(id < 0)
 11   {
 12     return 1;
 13   }
 14   else if(id > 0)
 15   {
 16     int cnt = 5;
 17     while(cnt)
 18     {
 19       printf("这是父进程,运行时间:%d\n",cnt--);
 20       sleep(1);
 21     
 22     }
 23     printf("父进程dead!:%d\n",cnt--);
 24     exit(2);                                                                                                
 25   }
 26   else 
 27   {
 28     while(1)
 29     {
 30       printf("这是子进程,持续运行\n");
 31       sleep(1);
 32     }
 33 
 34 
 35   }
 36 
 37 
 38   return 0;
 39 }
 40 

四、监视:

执行以下命令:

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

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

父进程未退出时:

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

父进程退出后: 

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

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

五、创建多进程

1、myprocess.c

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>


#define N 10

void worker()
{
  int cnt = 10;
  while(cnt)
  {
    printf("我是子进程,pid: %d, ppid:%d ,cnt: %d\n", getpid(),getppid(), cnt);
    sleep(1);
    cnt--;
  }
}

typedef void (*call_back_t)();


void createSubProcess(int n ,call_back_t cb)
{
  int i = 0;
  for(i = 0; i < n; i++)
  {
    sleep(1);

    pid_t id = fork();

    if(id == 0)
    {
      printf("创建子进程:%d\n", i);

      cb();
      exit(0);
    }

  }
}
      
int main()
{
  createSubProcess(N, worker);

  sleep(100);

  return 0;
}

2、运行myprocess.c

 

 

3、监视

  • 21
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杯酒问苍天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值