linux 下创建子进程

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhang_referee/article/details/82558642

1.创建单个子进程

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{

pid_t pid;

printf("the program is begining ...\n ");

pid = fork();

if(pid == -1){

        perror("fork son process failed:\n")    ;
        exit(-1);
}else if(pid == 0){

        printf("create son process successful!\n");
        printf("the son process id is %u\t,parent process id is %u\n",getpid(),getppid());

}else{

        printf("the son process id is %u\t,parent process id is %u\n",getpid(),getppid());

}


printf("the progran is ending ....\n");
return 0;

}
 

编译运行:

[zhang@bogon C]$ 
[zhang@bogon C]$ gcc -o fork_1 fork_1.c 
[zhang@bogon C]$ ./fork_1
the program is begining ...
 the son process id is 2022    ,parent process id is 1704
the progran is ending ....
[zhang@bogon C]$  create son process successful!
the son process id is 2023    ,parent process id is 1
the progran is ending ....
 

为了让运行结果,看起来不那么别扭,稍微修改下源代码,重新编译:

修改后的源码如下:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <unistd.h>
  4 
  5 int main()
  6 {
  7 
  8 pid_t pid;
  9 
 10 printf("the program is begining ...\n ");
 11 
 12 pid = fork();
 13 
 14 if(pid == -1){
 15 
 16         perror("fork son process failed:\n")    ;
 17         exit(-1);
 18 }else if(pid == 0){
 19 
 20         printf("create son process successful!\n");
 21         printf("the son process id is %u\t,parent process id is %u\n",getpid(),getppid());
 22 
 23 }else{
 24 
 25         sleep(3);
 26         printf("the son process id is %u\t,parent process id is %u\n",getpid(),getppid());
 27 
 28 }
 29 
 30 
 31 printf("the progran is ending ....\n");
 32 return 0;
 33 
 34 }
 

编译运行:

[zhang@bogon C]$ gcc -o fork_1 fork_1.c
[zhang@bogon C]$ ./fork_1
the program is begining ...
 create son process successful!
the son process id is 2036    ,parent process id is 2035
the progran is ending ....
 the son process id is 2035    ,parent process id is 1704
the progran is ending ....
[zhang@bogon C]$ ps -aux | grep 2035
zhang      2038  0.0  0.0 112708   972 pts/0    R+   15:24   0:00 grep --color=auto 2035
[zhang@bogon C]$ ps -aux | grep 1704
zhang      1704  0.0  0.2 115556  2164 pts/0    S    11:54   0:00 bash
zhang      2040  0.0  0.0 112708   972 pts/0    R+   15:24   0:00 grep --color=auto 1704
[zhang@bogon C]$ 

 

可以看到,fork后,程序由单分支变成了多分支,并且fork之前的代码只执行一次。

2.循环创建n个子进程

先附上代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{

pid_t pid;
int i;

for(i = 0; i < 3; i++){

        pid = fork();

        if(pid == -1){

                perror("create son process failed !\n") ;

        }else if(pid == 0) {
    
                printf("create son process ok,son process pid is %u\t,parent process pid is %u\n",getpid(),getppid());
    
        }else {

                printf("create son process ok,son process pid is %u\t,parent process pid is %u\n",getpid(),getppid());

        }    
}

printf("the programming will ending..\n");

return 0;

}
 

编译运行:

[zhang@bogon C]$ gcc -o multiProcess_1 multiProcess_1.c
[zhang@bogon C]$ ./multiProcess_1 
create son process ok,son process pid is 5039    ,parent process pid is 1704
create son process ok,son process pid is 5039    ,parent process pid is 1704
create son process ok,son process pid is 5039    ,parent process pid is 1704
the programming will ending..
[zhang@bogon C]$ create son process ok,son process pid is 5040    ,parent process pid is 1
create son process ok,son process pid is 5040    ,parent process pid is 1
create son process ok,son process pid is 5040    ,parent process pid is 1
the programming will ending..
create son process ok,son process pid is 5041    ,parent process pid is 1
create son process ok,son process pid is 5041    ,parent process pid is 1
the programming will ending..
create son process ok,son process pid is 5042    ,parent process pid is 1
the programming will ending..
create son process ok,son process pid is 5043    ,parent process pid is 1
create son process ok,son process pid is 5043    ,parent process pid is 1
the programming will ending..
create son process ok,son process pid is 5044    ,parent process pid is 1
the programming will ending..
create son process ok,son process pid is 5045    ,parent process pid is 1
the programming will ending..
create son process ok,son process pid is 5046    ,parent process pid is 1
the programming will ending..
ls
char    environ    fork    fork_1.c  list    malloc    multiProcess    multiProcess_1.c  sizeof    sizeof_11   sizeof.c  socket.c
char.c  environ.c  fork_1  fork.c    list.c  malloc.c  multiProcess_1  multiProcess.c    sizeof_1  sizeof_1.c  socket
[zhang@bogon C]$ 
 

惊讶的发现,我不过是想循环创建3个子进程而已,为何一下子会创建这么多,原来这样这写,父进程会创建子进程,而子进程又会创建子进程,上面代码创建子进程的方式执行原理图如下所示:

好了,那如何只创建3(n)个子进程(而不是父进程创建子进程,子进程再创建子进程),先附上解决方案 :

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{

pid_t pid;
int i;

for(i = 0; i < 3; i++){

        pid = fork();

        if(pid == -1){

                perror("create son process failed !\n") ;

        }else if(pid == 0) {

                break; //这里是关键
                //printf("create son process ok,son process pid is %u\t,parent process pid is %u\n",getpid(),getppid());

        }else {

                printf("create son process ok,son process pid is %u\t,parent process pid is %u\n",getpid(),getppid());

        }
}

printf("the programming will ending..\n");

return 0;

}

在上例中,当pid == 0时,直接break跳出循环去执行for循环后面的代码,这就是关键,为什么这么做,主要是因为fork这个函数的返回值,如上述代码所示,失败返回-1,成功返回:① 父进程返回子进程的ID(非负)    ②子进程返回 0 !这里附上fork函数的man fork返回值:

RETURN VALUE
       On  success,  the PID of the child process is returned in the parent,
       and 0 is returned in the child.  On failure, -1 is  returned  in  the
       parent, no child process is created, and errno is set appropriately.

顺便提下:getpid()和getppid()的作用分别是获取进程pid和父进程pid。

3.父子进程之间在fork后。有哪些相同,那些相异之处呢?
刚fork之后:
父子相同处: 全局变量、.data、.text、栈、堆、环境变量、用户ID、宿主目录、进程工作目录、信号处理方式...
父子不同处: 1.进程ID   2.fork返回值   3.父进程ID    4.进程运行时间    5.闹钟(定时器)   6.未决信号集
似乎,子进程复制了父进程0-3G用户空间内容,以及父进程的PCB,但pid不同。真的每fork一个子进程都要将父进程的0-3G地址空间完全拷贝一份,然后在映射至物理内存吗?
当然不是!父子进程间遵循读时共享写时复制的原则。这样设计,无论子进程执行父进程的逻辑还是执行自己的逻辑都能节省内存开销。   
 

猜你喜欢

转载自blog.csdn.net/zhang_referee/article/details/82558642