进程是一种动态描述,但是并不代表所有的进程都在运行。进程有两个基本元素,一个是程序代码(可能被执行相同程序的其他程序共享)和代码相关联的数据集。

任何计算机都包含一个基本的程序集合,称为操作系统(它的上层是shell),它的目的:往下,与硬件交互,管理所有的硬件资源;往上,为用户程序提供一个良好的执行环境。

我们应该知道程序是一个二进制文件,它存在与硬盘,当它运行的时候就有了动态的属性,此时有了两份拷贝,一份在硬盘,一份在内存(我们把内存中的程序叫做进程)此时的管理对象变成了内存中的可执行程序,而要管理的话就需要先描述,描述就需要一个结构体来包含进程中所有的信息。PCB就是来描述进程的,PCB就是一个个结构体。

进程的描述:必须要有PID,每个进程在内核中都有一个进程控制块(PCB)来维护进程的相关信息,linux内核的进程控制块是task_struct结构体。  

task_struct与PCB之间的关系:PCB是进程控制块的统称,而task_struct是一种数据结构。

如何创建一个子进程:用fork函数创建一个子进程,有两个返回值,第一个返回值是给父进程返回子进程的PID,第二个是给子进程返回0。fork之后要创建新进程,但是大多数以父进程为模板,所以对代码是共享的,对数据是以写时拷贝的方式一人一份(代码具有只读行),具体操作如下:

我们首先创建mypid.c然后写入代码:

java应用创建子进程JNI java子进程创建和使用_父进程

运行代码之后我们可以看到打印了两遍,如图所示:

java应用创建子进程JNI java子进程创建和使用_子进程_02

那我们如何区分父进程和子进程呢?我们可以将mypid.c中的代码改写为:

java应用创建子进程JNI java子进程创建和使用_父进程_03

运行代码可以看到:

java应用创建子进程JNI java子进程创建和使用_父进程_04

以上就是子进程与父进程之间的关系,注意观察父进程的pid与子进程的ppid,他们是一样的。

我们修改mypid.c中的程序,加入一个全局变量,如图所示:

java应用创建子进程JNI java子进程创建和使用_父进程_05

其运行结果为:

java应用创建子进程JNI java子进程创建和使用_java应用创建子进程JNI_06

可以看到,他们的值是不一样的,但是地址一样,这是因为我们所说的内存是虚拟内存,如果要在物理地址中找到对应的值的话还需要经过页表和mmu,而虚表的位置在栈和堆之间。