fork函数用于创立子进程,典型的调用一次,回来两次的函数,其间回来子进程的PID和0,其间调用进程回来了子进程的PID,而子进程则回来了0,这是一个比较有意思的函数,可是两个进程的履行次序是不定的。fork 函数调用完结以后父进程的虚拟存储空间被仿制给了子进程的虚拟存储空间,因而也就完成了同享文件等操作。可是虚拟的存储空间映射到物理存储空间的进程中采用了写时仿制技能(详细的操作巨细是按着页操控的),该技能首要是将多进程中相同的目标(数据)在物理存储其间只要一个物理存储空间,而当其间的某一个进程妄图对该区域进行写操作时,内核就会在物理存储器中拓荒一个新的物理页面,将需求写的区域内容仿制到新的物理页面中,然后对新的物理页面进行写操作。这时便是完成了对不同进程的操作而不会产生影响其他的进程,一起也节省了许多的物理存储器。
#include
#include
#include
#include
#include
#include
int main()
{
char p = g;
int number = 11;
if(fork()==0) /*子进程*/
{
p = c; /*子进程对数据的修正*/
printf(“p = %c , number = %d “,p,number);
exit(0);
}
/*父进程*/
number = 14; /*父进程对数据修正*/
printf(“p = %c , number = %d “,p,number);
exit(0);
}
编译调试:
[gong@Gong-Computer cprogram]$ gcc -g TestWriteCopyTech.c -o TestWriteCopyTech
[gong@Gong-Computer cprogram]$ ./TestWriteCopyTech
p = g , number = 14 —–父进程打印内容
[gong@Gong-Computer cprogram]$ p = c , number = 11 —–子进程打印内容
原因剖析:
因为存在妄图进行写操作的部分,因而会产生写时仿制进程,子进程中对数据的修正,内核就会创立一个新的物理内存空间。然后再次将数据写入到新的物理内存空间中。可知,对新的区域的修正不会改动原有的区域,这样不同的空间就区别开来。可是没有修正的区域仍然是多个进程之间同享。
fork函数的代码段基本是只读类型的,并且在运转阶段也仅仅仿制,并不会对内容进行修正,因而父子进程是同享代码段,而数据段、Bss段、仓库段等会在运转的进程中产生写进程,这样就导致了不同的段产生相应的写时仿制进程,完成了不同进程的独立空间。
可是需求留意的是文件操作,因为文件的操作是经过文件描述符表、文件表、v-node表三个联系起来操控的,其间文件表、v-node表是一切的进程同享,而每个进程都存在一个独立的文件描述符表。父子进程虚拟存储空间的内容是大致相同的,父子进程是经过同一个物理区域存储文件描述符表,但假如修正文件描述符表,也会产生写时仿制操作,只要这样才干确保子进程中对文件描述符的修正,不会影响到父进程的文件描述符表。例如close操作,因为close会导致文件的描述符的值产生变化,相当于产生了写操作,这是产生了写时仿制进程,完成新的物理空间,然后再次产生close操作,这样就不会产生子进程中文件描述符的封闭而导致父进程不能拜访文件。
测试函数:
#include
#include
#include
#include
#include
#include
#include
int main()
{
int fd;
char c[3];
char *s = “TestFs”;
fd = open(“foobar.txt”,O_RDWR,0);
if(fork()==0) //子进程
{
fd = 1;//stdout
write(fd,s,7);
exit(0);
}
//父进程
read(fd,c,2);
c[2]=;
printf(“c = %s”,c);
exit(0);
}
[gong@Gong-Computer cprogram]$ gcc -g fileshare2.c -o fileshare2
[gong@Gong-Computer cprogram]$ ./fileshare2
c = fo —-foobar.txt中的内容
[gong@Gong-Computer cprogram]$ TestFs —规范输出
原因剖析:因为父子进程的文件描述符表是相同的,可是在子进程中对fd(文件描述符表中的项)进行了修正,这时会产生写时仿制进程,内核在物理内存中分配一个新的页面存储子进程原文件描述符fd存在页面的内容,然后再进修写操作,完成将fd修正为1,也便是规范输出。可是父进程的fd并没有产生改动,仍是与其他的子进程同享文件描述符表,因而仍然是对文件foobar.txt进行操作。
因而需求首要fork函数实质上是按着写时仿制的方法完成文件的映射,并不是同享,写时仿制操作使得内存的需求量大大的减少了,详细的写时仿制完成,请参看十分经典的“深化了解计算机体系”的第622页。