����8-8 linux/kernel/fork.c


  1 /*

  2  *  linux/kernel/fork.c

  3  *

  4  *  (C) 1991  Linus Torvalds

  5  */

  6

  7 /*

  8  *  'fork.c' contains the help-routines for the 'fork' system call

  9  * (see also system_call.s), and some misc functions ('verify_area').

 10  * Fork is rather simple, once you get the hang of it, but the memory

 11  * management can be a bitch. See 'mm/mm.c': 'copy_page_tables()'

 12  */

    /*

     * 'fork.c'�к���ϵͳ����'fork'�ĸ����ӳ��򣨲μ�system_call.s�����Լ�һЩ

     * ����������'verify_area'����һ�����˽���fork���ͻᷢ�����Ƿdz��򵥵ģ���

     * �ڴ����ȴ��Щ�Ѷȡ��μ�'mm/memory.c'�е�'copy_page_tables()'������

     */

 13 #include <errno.h>        // �����ͷ�ļ�������ϵͳ�и��ֳ����š�

 14

 15 #include <linux/sched.h>  // ���ȳ���ͷ�ļ�������������ṹtask_struct������0�����ݡ�

 16 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣

 17 #include <asm/segment.h>  // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����

 18 #include <asm/system.h>   // ϵͳͷ�ļ������������û��޸�������/�ж��ŵȵ�Ƕ��ʽ���ꡣ

 19

    // дҳ����֤����ҳ�治��д������ҳ�档������mm/memory.c ��261�п�ʼ��

 20 extern void write_verify(unsigned long address);

 21

 22 long last_pid=0;          // ���½��̺ţ���ֵ����get_empty_process()���ɡ�

 23

    //// ���̿ռ�����дǰ��֤������

    // ����80386 CPU����ִ����Ȩ��0����ʱ���������û��ռ��е�ҳ���Ƿ���ҳ�����ģ����

    // ��ִ���ں˴���ʱ�û��ռ�������ҳ�汣����־�������ã�дʱ���ƻ���Ҳ��ʧȥ�����á�

    // verify_area()���������ڴ�Ŀ�ġ�������80486�������CPU������ƼĴ���CR0����һ��

    // д������־WP��λ16�����ں˿���ͨ�����øñ�־����ֹ��Ȩ��0�Ĵ������û��ռ�ֻ��

    // ҳ��ִ��д���ݣ����򽫵��·���д�����쳣���Ӷ�486����CPU����ͨ�����øñ�־����

    // ��ʹ�ñ�����ͬ����Ŀ�ġ�

    // �ú����Ե�ǰ�����߼���ַ�� addr �� addr + size ��һ�η�Χ��ҳΪ��λִ��д����ǰ

    // �ļ����������ڼ���ж�����ҳ��Ϊ��λ���в�������˳���������Ҫ�ҳ�addr����ҳ

    // �濪ʼ��ַstart��Ȼ�� start���Ͻ������ݶλ�ַ��ʹ���start�任��CPU 4G���Կ�

    // ���еĵ�ַ�����ѭ������write_verify() ��ָ����С���ڴ�ռ����дǰ��֤����ҳ��

    // ��ֻ���ģ���ִ�й�������͸���ҳ�������дʱ���ƣ���

 24 void verify_area(void * addr,int size)

 25 {

 26         unsigned long start;

 27

    // ���Ƚ���ʼ��ַstart����Ϊ������ҳ����߽翪ʼλ�ã�ͬʱ��Ӧ�ص�����֤�����С��

    // �¾��е� start & 0xfff �������ָ����ʼλ��addr��Ҳ��start��������ҳ���е�ƫ��

    // ֵ��ԭ��֤��Χ size �������ƫ��ֵ����չ���� addr ����ҳ����ʼλ�ÿ�ʼ�ķ�Χֵ��

    // ����� 30���� Ҳ��Ҫ����֤��ʼλ�� start ������ҳ��߽�ֵ���μ�ǰ���ͼ���ڴ���

    // ֤��Χ�ĵ�������

 28         start = (unsigned long) addr;

 29         size += start & 0xfff;

 30         start &= 0xfffff000;               // ��ʱstart�ǵ�ǰ���̿ռ��е��߼���ַ��

    // ����� start ���Ͻ������ݶ������Ե�ַ�ռ��е���ʼ��ַ�����ϵͳ�������Կռ��еĵ�

    // ַλ�á�����Linux 0.1x�ںˣ������ݶκʹ���������Ե�ַ�ռ��еĻ�ַ���޳�����ͬ��

    // Ȼ��ѭ������дҳ����֤����ҳ�治��д������ҳ�档��mm/memory.c��274�У�

 31         start += get_base(current->ldt[2]);     // include/linux/sched.h��277�С�

 32         while (size>0) {

 33                 size -= 4096;

 34                 write_verify(start);

 35                 start += 4096;

 36         }

 37 }

 38

    // �����ڴ�ҳ����

    // ����nr��������ţ�p�����������ݽṹָ�롣�ú���Ϊ�����������Ե�ַ�ռ������ô���

    // �κ����ݶλ�ַ���޳���������ҳ����  ����Linuxϵͳ������дʱ���ƣ�copy on write��

    // ������ ��������Ϊ�½��������Լ���ҳĿ¼�����ҳ�����û��ʵ��Ϊ�½��̷�������

    // �ڴ�ҳ�档��ʱ�½������丸���̹��������ڴ�ҳ�档�����ɹ�����0�����򷵻س����š�

 39 int copy_mem(int nr,struct task_struct * p)

 40 {

 41         unsigned long old_data_base,new_data_base,data_limit;

 42         unsigned long old_code_base,new_code_base,code_limit;

 43

    // ����ȡ��ǰ���ֲ̾����������д���������������ݶ����������еĶ��޳����ֽ�������

    // 0x0f�Ǵ����ѡ�����0x17�����ݶ�ѡ�����Ȼ��ȡ��ǰ���̴���κ����ݶ������Ե�ַ

    // �ռ��еĻ���ַ������Linux 0.12�ں˻���֧�ִ�������ݶη�������������������Ҫ

    // ������κ����ݶλ�ַ�Ƿ���ͬ������Ҫ�����ݶεij������ٲ�С�ڴ���εij���

    // ���μ�ͼ5-12���������ں���ʾ������Ϣ����ֹͣ���С�

    // get_limit()��get_base()������include/linux/sched.h��277�к�279�д���

 44         code_limit=get_limit(0x0f);

 45         data_limit=get_limit(0x17);

 46         old_code_base = get_base(current->ldt[1]);

 47         old_data_base = get_base(current->ldt[2]);

 48         if (old_data_base != old_code_base)

 49                 panic("We don't support separate I&D");

 50         if (data_limit < code_limit)

 51                 panic("Bad data_limit");

    // Ȼ�����ô����е��½��������Ե�ַ�ռ��еĻ���ַ���ڣ�64MB * ������ţ������ø�ֵ

    // �����½��ֲ̾����������ж��������еĻ���ַ�����������½��̵�ҳĿ¼�����ҳ���

    // �����Ƶ�ǰ���̣������̣���ҳĿ¼�����ҳ��� ��ʱ�ӽ��̹��������̵��ڴ�ҳ�档

    // ���������copy_page_tables()����0�������ʾ���������ͷŸ������ҳ���

 52         new_data_base = new_code_base = nr * TASK_SIZE;

 53         p->start_code = new_code_base;

 54         set_base(p->ldt[1],new_code_base);

 55         set_base(p->ldt[2],new_data_base);

 56         if (copy_page_tables(old_data_base,new_data_base,data_limit)) {

 57                 free_page_tables(new_data_base,data_limit);

 58                 return -ENOMEM;

 59         }

 60         return 0;

 61 }

 62

 63 /*

 64  *  Ok, this is the main fork-routine. It copies the system process

 65  * information (task[nr]) and sets up the necessary registers. It

 66  * also copies the data segment in it's entirety.

 67  */

    /*

     * OK����������Ҫ��fork�ӳ���������ϵͳ������Ϣ(task[n])

     * �������ñ�Ҫ�ļĴ��������������ظ������ݶΣ�Ҳ�Ǵ���Σ���

     */

    // ���ƽ��̡�

    // �ú����IJ����ǽ���ϵͳ�����жϴ������̣�sys_call.s����ʼ��ֱ�����ñ�ϵͳ���ô���

    // ���̣�sys_call.s��208�У��͵��ñ�����ǰ��sys_call.s��217�У���ѹ������ں�

    // ̬ջ�ĸ��Ĵ�����ֵ����Щ��sys_call.s��������ѹ���ں�̬ջ��ֵ������������:

    // �� CPUִ���ж�ָ��ѹ����û�ջ��ַss��esp����־eflags�ͷ��ص�ַcs��eip��

    // �� ��83--88���ڸս���system_callʱ��ջ�ĶμĴ���ds��es��fs��edx��ecx��edx��

    // �� ��94�е���sys_call_table��sys_fork����ʱ��ջ�ķ��ص�ַ������none��ʾ����

    // �� ��212--216���ڵ���copy_process()֮ǰ��ջ��gs��esi��edi��ebp��eax��nr����

    // ���в���nr�ǵ���find_empty_process()���������������š�

 68 int copy_process(int nr,long ebp,long edi,long esi,long gs,long none,

 69                 long ebx,long ecx,long edx, long orig_eax,

 70                 long fs,long es,long ds,

 71                 long eip,long cs,long eflags,long esp,long ss)

 72 {

 73         struct task_struct *p;

 74         int i;

 75         struct file *f;

 76

    // ����Ϊ���������ݽṹ�����ڴ档����ڴ����������򷵻س����벢�˳���Ȼ��������

    // �ṹָ��������������nr���С�����nrΪ����ţ���ǰ��find_empty_process()���ء�

    // ���Űѵ�ǰ��������ṹ���ݸ��Ƶ������뵽���ڴ�ҳ��p��ʼ����

 77         p = (struct task_struct *) get_free_page();

 78         if (!p)

 79                 return -EAGAIN;

 80         task[nr] = p;

 81         *p = *current/* NOTE! this doesn't copy the supervisor stack */

                            /* ע�⣡���������Ḵ�Ƴ����û���ջ��ֻ���ƽ��̽ṹ��*/

    // ���Ը������Ľ��̽ṹ���ݽ���һЩ�޸ģ���Ϊ�½��̵�����ṹ���Ƚ��½��̵�״̬

    // ��Ϊ�����жϵȴ�״̬���Է�ֹ�ں˵�����ִ�С�Ȼ�������½��̵Ľ��̺�pid������ʼ

    // ����������ʱ��Ƭֵ������ priorityֵ�� һ��Ϊ15����ણ������Ÿ�λ�½��̵��ź�

    // λͼ��������ʱֵ���Ự��session���쵼��־ leader�� ���̼����ӽ������ں˺��û�

    // ̬����ʱ��ͳ��ֵ�������ý��̿�ʼ���е�ϵͳʱ��start_time��

 82         p->state = TASK_UNINTERRUPTIBLE;

 83         p->pid = last_pid;           // �½��̺š�Ҳ��find_empty_process()�õ���

 84         p->counter = p->priority;    // ����ʱ��Ƭֵ�����������

 85         p->signal = 0;               // �ź�λͼ��

 86         p->alarm = 0;                // ������ʱֵ�����������

 87         p->leader = 0;               /* process leadership doesn't inherit */

                                         /* ���̵��쵼Ȩ�Dz��ܼ̳е� */

 88         p->utime = p->stime = 0;     // �û�̬ʱ��ͺ���̬����ʱ�䡣

 89         p->cutime = p->cstime = 0;   // �ӽ����û�̬�ͺ���̬����ʱ�䡣

 90         p->start_time = jiffies;     // ���̿�ʼ����ʱ�䣨��ǰʱ��δ�������

    // ���޸�����״̬��TSS ���ݣ��μ��б���˵����������ϵͳ������ṹ p������1ҳ��

    // �ڴ棬���� (PAGE_SIZE + (long) p) ��esp0����ָ���ҳ���ˡ� ss0:esp0 ��������

    // ���ں�ִ̬��ʱ��ջ�����⣬�ڵ�3���������Ѿ�֪����ÿ�������� GDT���ж�������

    // ����������һ���������TSS������������һ���������LDT����������������111��

    // �����ǰ�GDT�б�����LDT����������ѡ��������ڱ������TSS���С���CPUִ��

    // �л�����ʱ�����Զ���TSS�а�LDT����������ѡ������ص�ldtr�Ĵ����С�

 91         p->tss.back_link = 0;

 92         p->tss.esp0 = PAGE_SIZE + (long) p;  // �����ں�̬ջָ�롣

 93         p->tss.ss0 = 0x10;           // �ں�̬ջ�Ķ�ѡ��������ں����ݶ���ͬ����

 94         p->tss.eip = eip;            // ָ�����ָ�롣

 95         p->tss.eflags = eflags;      // ��־�Ĵ�����

 96         p->tss.eax = 0;              // ���ǵ�fork()����ʱ�½��̻᷵��0��ԭ�����ڡ�

 97         p->tss.ecx = ecx;

 98         p->tss.edx = edx;

 99         p->tss.ebx = ebx;

100         p->tss.esp = esp;

101         p->tss.ebp = ebp;

102         p->tss.esi = esi;

103         p->tss.edi = edi;

104         p->tss.es = es & 0xffff;     // �μĴ�����16λ��Ч��

105         p->tss.cs = cs & 0xffff;

106         p->tss.ss = ss & 0xffff;

107         p->tss.ds = ds & 0xffff;

108         p->tss.fs = fs & 0xffff;

109         p->tss.gs = gs & 0xffff;

110         p->tss.ldt = _LDT(nr);       // ����ֲ�����������ѡ�����LDT��������GDT�У���

111         p->tss.trace_bitmap = 0x80000000;       //����16λ��Ч����

    // �����ǰ����ʹ����Э���������ͱ����������ġ����ָ��clts����������ƼĴ���CR0

    // �е������ѽ�����TS����־��ÿ�����������л���CPU�������øñ�־���ñ�־���ڹ���

    // ��ѧЭ������������ñ�־��λ����ôÿ��ESCָ��ᱻ�����쳣7�������Э����

    // �����ڱ�־MPҲͬʱ��λ�Ļ�����ôWAITָ��Ҳ�Ჶ����ˣ���������л�������һ

    // ��ESCָ�ʼִ��֮����Э�������е����ݾͿ�����Ҫ��ִ���µ�ESCָ��֮ǰ����

    // ����������������ᱣ��Э�����������ݲ���λTS��־��ָ��fnsave���ڰ�Э������

    // ������״̬���浽Ŀ�IJ�����ָ�����ڴ������У�tss.i387����

112         if (last_task_used_math == current)

113                 __asm__("clts ; fnsave %0 ; frstor %0"::"m" (p->tss.i387));

 

    // ���������ƽ���ҳ�����������Ե�ַ�ռ����������������κ����ݶ��������еĻ�ַ

    // ���޳���������ҳ�����������������ֵ����0������λ������������Ӧ��ͷ�Ϊ

    // ��������������������ṹ���ڴ�ҳ��

114         if (copy_mem(nr,p)) {              // ���ز�Ϊ0��ʾ������

115                 task[nr] = NULL;

116                 free_page((long) p);

117                 return -EAGAIN;

118         }

    // ��������������ļ��Ǵ򿪵ģ��򽫶�Ӧ�ļ��Ĵ򿪴�����1����Ϊ���ﴴ�����ӽ���

    // ���븸���̹�����Щ�򿪵��ļ�������ǰ���̣������̣���pwd, root��executable

    // ���ô�������1��������ͬ���ĵ������ӽ���Ҳ��������Щi�ڵ㡣

119         for (i=0; i<NR_OPEN;i++)

120                 if (f=p->filp[i])

121                         f->f_count++;

122         if (current->pwd)

123                 current->pwd->i_count++;

124         if (current->root)

125                 current->root->i_count++;

126         if (current->executable)

127                 current->executable->i_count++;

128         if (current->library)

129                 current->library->i_count++;

    // �����GDT��������������TSS�κ�LDT����������������ε��޳��������ó�104

    // �ֽڡ��μ� include/asm/system.h��52��66 �д��롣 Ȼ�����ý���֮��Ĺ�ϵ����

    // ָ�룬�����½��̲��뵽��ǰ���̵��ӽ��������С����½��̵ĸ���������Ϊ��ǰ���̣�

    // ���½��̵������ӽ���ָ��p_cptr �������ֵܽ���ָ��p_ysptr�ÿա��������½���

    // �����ֽ���ָ��p_osptr���õ��ڸ����̵������ӽ���ָ�롣����ǰ����ȴ�ǻ�������

    // �ӽ��̣����ñ������ֽ��̵����������ָ��p_yspter ָ���½��̡����ѵ�ǰ����

    // �������ӽ���ָ��ָ������½��̡�Ȼ����½������óɾ���̬����󷵻��½��̺š�

    // ���⣬ set_tss_desc() �� set_ldt_desc() ������ include/asm/system.h �ļ��С�

    // ��gdt+(nr<<1)+FIRST_TSS_ENTRY��������nr��TSS����������ȫ�ֱ��еĵ�ַ����Ϊ

    // ÿ������ռ��GDT����2������ʽ��Ҫ����'(nr<<1)'��

    // ��ע�⣬�������л�ʱ������Ĵ���tr����CPU�Զ����ء�

130         set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss));

131         set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&(p->ldt));

132         p->p_pptr = current;               // �����½��̵ĸ�����ָ�롣

133         p->p_cptr = 0;                     // ��λ�½��̵������ӽ���ָ�롣

134         p->p_ysptr = 0;                    // ��λ�½��̵ı��������ֵܽ���ָ�롣

135         p->p_osptr = current->p_cptr;      // �����½��̵ı��������ֵܽ���ָ�롣

136         if (p->p_osptr)                    // ���½����������ֵܽ��̣�������

137                 p->p_osptr->p_ysptr = p;   // ��������ֵ�ָ��ָ���½��̡�

138         current->p_cptr = p;               // �õ�ǰ���������ӽ���ָ��ָ���½��̡�

139         p->state = TASK_RUNNING;        /* do this last, just in case */

140         return last_pid;

141 }

142

    // Ϊ�½���ȡ�ò��ظ��Ľ��̺�last_pid���������������������е������(������)��

143 int find_empty_process(void)

144 {

145         int i;

146

    // ���Ȼ�ȡ�µĽ��̺š����last_pid��1�󳬳����̺ŵ�������ʾ��Χ�������´�1��ʼ

    // ʹ��pid�š� Ȼ�����������������������õ�pid���Ƿ��Ѿ����κ�����ʹ�á��������

    // ��ת��������ʼ�����»��һ��pid�š� ����������������Ϊ������Ѱ��һ���������

    // ������š� last_pid��һ��ȫ�ֱ��������÷��ء������ʱ����������64�����Ѿ���ȫ

    // ��ռ�ã��򷵻س����롣

147         repeat:

148                 if ((++last_pid)<0) last_pid=1;

149                 for(i=0 ; i<NR_TASKS ; i++)

150                         if (task[i] && ((task[i]->pid == last_pid) ||

151                                         (task[i]->pgrp == last_pid)))

152                                 goto repeat;

153         for(i=1 ; i<NR_TASKS ; i++)             // ����0��ų����⡣

154                 if (!task[i])

155                         return i;

156         return -EAGAIN;

157 }

158