fork多进程

每个进程都有一个非负整数的PID,可以通过下面函数返回

#include <unistd.h>

//进程ID
pid_t getpid(void);

//父进程ID
pid_t getppid(void);

而调用fork函数可以创建新进程,即子进程;fork被调用一次,就好像copy了一份副本,返回两次,父进程的返回值是子进程的进程ID,子进程的返回值是0

在调用fork之后,子进程获得了父进程的数据空间,堆栈的副本,但这仅仅是副本,父进程和子进程并不共享这些存储空间

可以通过下面小程序来确定fork的两次返回:

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

int main(){
        int a = 1;
        pid_t pid;
        if ((pid = fork()) < 0) {
                printf("fork error\n");
                exit(1);
        } else if (pid == 0){
                printf("fork child process: return %d\n", pid);
                ++a;
        } else {
                printf("fork parent process: return %d\n", pid);
                --a;
        }
        printf("process pid %d: a = %d\n", getpid(), a);
        return 0;
}

else if里fork返回的pid为0,应该是子进程;假如为其它正数,就是父进程,这里直接将这个正数pid打印出来;最终再将父子进程所在的pid都打印出来,确认fork父进程返回的正数即是子进程的进程ID

编译运行一下,结果:

fork child process: return 0
process pid 4608: a = 2
fork parent process: return 4608
process pid 4000: a = 0

从结果可以看到子进程的进程ID为4608,因为子进程ID是在else if里printf输出之后打印的;而父进程fork的返回值也是4608,可见fork父进程返回的正数的确是子进程的进程ID,而子进程返回0

将可执行程序再次运行一下,结果发生了改变:

fork parent process: return 1356 fork child process: return 0 process pid 1608: a = 0

process pid 1356: a = 2

但是不论怎么变,上面一段结果不会改变,变得仅仅是父进程和子进程的打印顺序,也就是说fork之后父进程和子进程的执行顺序是不确定的,这取决于内核的调度算法,如果需要他们相互同步,则需要进程间通信

发表评论