java fork菜鸟_fork()函数的简单例子

2022-09-19 13:37:52

1.fork()函数

fork()是一个系统调用,用于创建进程。创建的这个进程与原来进程几乎完全相同。这个新产生的进程称为子进程。一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。需要注意的一点:就是调用fork之后,两个进程同时执行的代码段是fork函数之后的代码,而之前的代码已经由父进程执行完毕。下面来看一个很简单的例子。

fork()返回两个值

返回一个大于0的值给父进程

返回0给子进程

返回其他值说明fork失败了

2.关于fork的一个简单例子

#include

#include

int main()

{

pid_t pid;

int count = 0;

pid = fork();//fork一个进程

if(pid == 0) { //pid为0,

printf("this is child process, pid is %d\n",getpid());//getpid返回的是当前进程的PID

count+=2;

printf("count = %d\n",count);

} else if(pid > 0) {

printf("this is father process, pid is %d\n",getpid());

count++;

printf("count = %d\n",count);

} else {

fprintf(stderr,"ERROR:fork() failed!\n");

}

return 0;

}

下面是运行结果:

df695fed3d2a7651578694f8c7a8a4ad.png

有人可能会对这个运行结果产生一种错觉,就是程序中if语句的两条分支if(pid == 0)和else if(pid > 0)都得到了执行。其实完全不是这么回事,出现这种运行结果的原因是因为,在main()函数调用fork了,创建了一个新的进程,这个进程称为原来进程的子进程。子进程与原来的进程并发执行,谁先谁后没有规律,由操作系统调度决定。

我们用gdb工具对这个程序单步执行调试一下,可能会对这个过程了解的更清晰一些。

3.使用gdb调试父进程。

1.输入gdb a.out然后输入start开始调试,此时终端显示即将执行的代码

9474fa51e36e83f3657ab44c868b9e31.png

2.输入n,执行当前一行代码,同时显示下一条将执行的代码

58594decaa5f368c7f27f57cf02afc9e.png

即将创建一个子进程,当前进程为父进程。

3.再输入n执行pid=fork()语句

15c805d19b3b7a9c01e2b0839820acad.png

这个时候,终端上显示

Detaching after fork from child process 2755.

this is child process, pid is 2755

count = 2

这个时候,说明已经新建了一个子进程,子进程PID是2755,而且由于我们现在单步调试的是父进程,并不影响子进程的执行。这个子进程只有几行代码,这个时候已经执行完了,并且在终端上显示了执行结果,就是下面两行内容。

this is child process, pid is 2755

count = 2

4. 输入p pid看一下fork函数返回给父进程的值是不是子进程的PID

03794ecf082ed12acec309a70af79f45.png

果然就是子进程的PID值。

5.输入n接着执行判断语句

45edef43807f7b91e66a62d77ab15a7d.png

由于pid的值为2755,因此跳过了if(pid==0)分支内的语句,转而判断pid是否大于0

6.输入n接着判断pid是否大于0

4d0a9cf08ffb9bd0ec1f6f41e5644b5b.png

pid的值大于0,执行分支内的语句。

7.接着输入n,直到程序正常结束

23bee50d426c87e2203a3c7a9679a603.png

上面是父进程的调试过程,其实子进程也可以用gdb来调试,下次再说。

4.使用ps aux命令查看父进程和子进程

ps aux命令可以查看系统中正在运行的所有进程,不过我们这个例子代码很少,系统瞬间就能执行完毕,用ps aux命令根本捕捉不到。因此我们在代码中做一些修改。

#include

#include

int main()

{

pid_t pid;

int count = 0;

pid = fork();//fork一个进程

if(pid == 0) { //pid为0,

printf("this is child process, pid is %d\n",getpid());

count+=2;

printf("count = %d\n",count);

} else if(pid > 0) {

printf("this is father process, pid is %d\n",getpid());

count++;

printf("count = %d\n",count);

} else {

fprintf(stderr,"ERROR:fork() failed!\n");

}

sleep(10);//新加入的行,让程序在这里暂停10秒,父进程和子进程都会执行这行代码

return 0;

}

我们在第30行加入了一条语句,让程序暂停10s。重新编译程序,然后执行程序,输入./a.out后,快速切换到另外一个终端(如果你手速慢的话,多暂停一会儿就可以),输入ps aux查看正在运行的进程。

执行程序:

5c17dbd1a9a2c48899850737d91cc0a4.png

切换终端,输入ps aux查看进程

6c97b0a09b3da348f698f2cd34df8c82.png

可以看到a.out程序产生了两个进程,父进程PID是2928,子进程PID是2929。

  • 作者:滤石水
  • 原文链接:https://blog.csdn.net/weixin_30855927/article/details/115021260
    更新时间:2022-09-19 13:37:52