- // 複製進程。
- int
- copy_process (int nr, long ebp, long edi, long esi, long gs, long none,
- long ebx, long ecx, long edx,
- long fs, long es, long ds,
- long eip, long cs, long eflags, long esp, long ss)
- {
- struct task_struct *p;
- int i;
- struct file *f;
- p = (struct task_struct *) get_free_page (); // 爲新任務數據結構分配內存。
- if (!p) // 如果內存分配出錯,則返回出錯碼並退出。
- return -EAGAIN;
- task[nr] = p; // 將新任務結構指針放入任務數組中。
- // 其中nr 爲任務號,由前面find_empty_process()返回。
- *p = *current; /* NOTE! this doesn't copy the supervisor stack */
- /* 注意!這樣做不會複製超級用戶的堆棧 */ (只複製當前進程內容)。
- p->state = TASK_UNINTERRUPTIBLE; // 將新進程的狀態先置爲不可中斷等待狀態。
- p->pid = last_pid; // 新進程號。由前面調用find_empty_process()得到。
- p->father = current->pid; // 設置父進程號。
- p->counter = p->priority;
- p->signal = 0; // 信號位圖置0。
- p->alarm = 0;
- p->leader = 0; /* process leadership doesn't inherit */
- /* 進程的領導權是不能繼承的 */
- p->utime = p->stime = 0; // 初始化用戶態時間和核心態時間。
- p->cutime = p->cstime = 0; // 初始化子進程用戶態和核心態時間。
- p->start_time = jiffies; // 當前滴答數時間。
- // 以下設置任務狀態段TSS 所需的數據(參見列表後說明)。
- p->tss.back_link = 0;
- p->tss.esp0 = PAGE_SIZE + (long) p; // 堆棧指針(由於是給任務結構p 分配了1 頁
- // 新內存,所以此時esp0 正好指向該頁頂端)。
- p->tss.ss0 = 0x10; // 堆棧段選擇符(內核數據段)[??]。
- p->tss.eip = eip; // 指令代碼指針。
- p->tss.eflags = eflags; // 標誌寄存器。
- p->tss.eax = 0;
- p->tss.ecx = ecx;
- p->tss.edx = edx;
- p->tss.ebx = ebx;
- p->tss.esp = esp;
- p->tss.ebp = ebp;
- p->tss.esi = esi;
- p->tss.edi = edi;
- p->tss.es = es & 0xffff; // 段寄存器僅16 位有效。
- p->tss.cs = cs & 0xffff;
- p->tss.ss = ss & 0xffff;
- p->tss.ds = ds & 0xffff;
- p->tss.fs = fs & 0xffff;
- p->tss.gs = gs & 0xffff;
- p->tss.ldt = _LDT (nr); // 該新任務nr 的局部描述符表選擇符(LDT 的描述符在GDT 中)。
- p->tss.trace_bitmap = 0x80000000;
- (高16 ?揮行В?
- // 如果當前任務使用了協處理器,就保存其上下文。
- if (last_task_used_math == current)
- __asm__ ("clts ; fnsave %0"::"m" (p->tss.i387));
- // 設置新任務的代碼和數據段基址、限長並複製頁表。如果出錯(返回值不是0),則復位任務數組中
- // 相應項並釋放爲該新任務分配的內存頁。
- if (copy_mem (nr, p))
- { // 返回不爲0 表示出錯。
- task[nr] = NULL;
- free_page ((long) p);
- return -EAGAIN;
- }
- // 如果父進程中有文件是打開的,則將對應文件的打開次數增1。
- for (i = 0; i < NR_OPEN; i++)
- if (f = p->filp[i])
- f->f_count++;
- // 將當前進程(父進程)的pwd, root 和executable 引用次數均增1。
- if (current->pwd)
- current->pwd->i_count++;
- if (current->root)
- current->root->i_count++;
- if (current->executable)
- current->executable->i_count++;
- // 在GDT 中設置新任務的TSS 和LDT 描述符項,數據從task 結構中取。
- // 在任務切換時,任務寄存器tr 由CPU 自動加載。
- set_tss_desc (gdt + (nr << 1) + FIRST_TSS_ENTRY, &(p->tss));
- set_ldt_desc (gdt + (nr << 1) + FIRST_LDT_ENTRY, &(p->ldt));
- p->state = TASK_RUNNING; /* do this last, just in case */
- /* 最後再將新任務設置成可運行狀態,以防萬一 */
- return last_pid; // 返回新進程號(與任務號是不同的)。
- }
fork()函數的主要實現(1)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.