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