fork.c

1.   /* 

2.   *  linux/kernel/fork.c 

3.   *                                //--fork()用于创建子进程 

4.   *  (C) 1991  Linus Torvalds 

5.   */  

6.   /* 

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

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

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

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

11. */  

12. #include <errno.h>  

13. #include <linux/sched.h>  

14. #include <linux/kernel.h>  

15. #include <asm/segment.h>  

16. #include <asm/system.h>  

17.                                 //--写页面验证,若页面不可写,则复制页面  

18. extern void write_verify(unsigned long address);  

19. long last_pid=0;  

20.                                 //--进程空间区域写前验证函数  

21. void verify_area(void * addr,int size)  

22. {  

23.     unsigned long start;  

24.     start = (unsigned long) addr;  

25.     size += start & 0xfff;  

26.     start &= 0xfffff000;  

27.     start += get_base(current->ldt[2]);        //--逻辑地址到线性地址的转换  

28.     while (size>0) {  

29.         size -= 4096;  

30.         write_verify(start);  

31.         start += 4096;  

32.     }  

33. }  

34. int copy_mem(int nr,struct task_struct * p)        //--复制内存页表  

35. {                                                //--由于采用写时复制技术,这里只复制目录和页表项,不分配内存  

36.     unsigned long old_data_base,new_data_base,data_limit;  

37.     unsigned long old_code_base,new_code_base,code_limit;  

38.     code_limit=get_limit(0x0f);                    //--取段限长  

39.     data_limit=get_limit(0x17);  

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

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

42.     if (old_data_base != old_code_base)  

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

44.     if (data_limit < code_limit)  

45.         panic("Bad data_limit");  

46.     new_data_base = new_code_base = nr * TASK_SIZE;  

47.     p->start_code = new_code_base;  

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

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

50.     if (copy_page_tables(old_data_base,new_data_base,data_limit)) {        //--复制页表  

51.         free_page_tables(new_data_base,data_limit);  

52.         return -ENOMEM;  

53.     }  

54.     return 0;  

55. }  

56. /* 

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

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

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

60. */                                    //--fork()子程序,它复制系统进程信息,设置寄存器,复制数据段(代码段)  

61. int copy_process(int nr,long ebp,long edi,long esi,long gs,long none,  

62.         long ebx,long ecx,long edx, long orig_eax,   

63.         long fs,long es,long ds,  

64.         long eip,long cs,long eflags,long esp,long ss)        //--复制进程  

65. {  

66.     struct task_struct *p;  

67.     int i;  

68.     struct file *f;  

69.     p = (struct task_struct *) get_free_page();                //--为新任务数据结构分配内存  

70.     if (!p)  

71.         return -EAGAIN;  

72.     task[nr] = p;  

73.     *p = *current;    /* NOTE! this doesn't copy the supervisor stack */  

74.     p->state = TASK_UNINTERRUPTIBLE;  

75.     p->pid = last_pid;  

76.     p->counter = p->priority;  

77.     p->signal = 0;  

78.     p->alarm = 0;  

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

80.     p->utime = p->stime = 0;  

81.     p->cutime = p->cstime = 0;  

82.     p->start_time = jiffies;  

83.     p->tss.back_link = 0;  

84.     p->tss.esp0 = PAGE_SIZE + (long) p;  

85.     p->tss.ss0 = 0x10;  

86.     p->tss.eip = eip;  

87.     p->tss.eflags = eflags;  

88.     p->tss.eax = 0;  

89.     p->tss.ecx = ecx;  

90.     p->tss.edx = edx;  

91.     p->tss.ebx = ebx;  

92.     p->tss.esp = esp;  

93.     p->tss.ebp = ebp;  

94.     p->tss.esi = esi;  

95.     p->tss.edi = edi;  

96.     p->tss.es = es & 0xffff;  

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

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

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

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

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

102.      p->tss.ldt = _LDT(nr);  

103.      p->tss.trace_bitmap = 0x80000000;  

104.      if (last_task_used_math == current)  

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

106.      if (copy_mem(nr,p)) {  

107.          task[nr] = NULL;  

108.          free_page((long) p);  

109.          return -EAGAIN;  

110.      }  

111.      for (i=0; i<NR_OPEN;i++)                    //--如果父进程中有文件是打开的,则将对应文件的打开次数增1  

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

113.              f->f_count++;  

114.      if (current->pwd)  

115.          current->pwd->i_count++;  

116.      if (current->root)  

117.          current->root->i_count++;  

118.      if (current->executable)  

119.          current->executable->i_count++;  

120.      if (current->library)  

121.          current->library->i_count++;  

122.      set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss));    //--在GDT表中设置新任务的TSSLDT  

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

124.      p->p_pptr = current;  

125.      p->p_cptr = 0;  

126.      p->p_ysptr = 0;  

127.      p->p_osptr = current->p_cptr;  

128.      if (p->p_osptr)  

129.          p->p_osptr->p_ysptr = p;  

130.      current->p_cptr = p;  

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

132.      return last_pid;  

133.  }  

134.  int find_empty_process(void)                        //--为新进程取得不重复的进程号last_pid  

135.  {  

136.      int i;  

137.      repeat:  

138.          if ((++last_pid)<0) last_pid=1;  

139.          for(i=0 ; i<NR_TASKS ; i++)  

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

141.                          (task[i]->pgrp == last_pid)))  

142.                  goto repeat;  

143.      for(i=1 ; i<NR_TASKS ; i++)  

144.          if (!task[i])  

145.              return i;  

146.      return -EAGAIN;  

147.  }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值