我们知道,Linux中线程是轻量级进程,但这句话怎么理解呢?就像现在小孩子都知道地球是圆的,但那只是别人告诉他的,他自己是没有感觉的。
fork主要做了什么?
我们知道,schedule函数按照一定策略从任务链表里中选出一个进行切换(早期是任务数组task[NR_TASKS],现在linux内核不采用任务数组,而是采用链表形式,这样就不会受到NR_TASKS最大任务数限制了)。所有fork的本意就是在创建一个task_struct 变量,然后填充结构体里面的内容,包括各寄存器的值,设置内核栈,复制原页表信息到新进程的页表等。其中复制页表信息的操作是:先申请一页内存作为新进程的页目录表,然后循环检查原目录表,如果目录项中有值,申请一页内存,并把此页填到新页目录表相同位置。接下来,对应原页表的内容,我们也可以才有同样方法,对存在的页表项申请内容,填充新页表,然后把原页面的内容拷贝到新页面。
但把所有页面都拷贝过来工作量太大了,所以linux只是把老页表的内容拷贝过来,让新老进程共享同一页面。也就是说,页目录表和页表都是新申请的内存(极端情况下需要1页页目录表和1024页页表,即需要1025页内存),但页表指向的内存(也就是进程实际代码和数据所在位置)共享。只有在一方有写操作时,才单独分配内存。
再进一步,如果我们只申请一页内存作为页目录表,把原目录内容拷过来,即连页表也共享呢?
更进一步,我们连页目录表也不申请了,直接指向原进程的也目录表。也就是说,虽然是2个进程,但实际的代码完全一样(clone了原进程)。这样的话,就可以占用更多的cpu时间片了。毕竟别的任务只有一份,我却有2份。
这大概就是线程了