设为首页 加入收藏

TOP

内核进程的复制(五)
2012-11-01 15:47:27 来源: 作者: 【 】 浏览:3007
Tags:内核 进程 复制

  
  在分配了栈后,调用setup_thread_stack确定栈内的布局。这个函数完成的操作是:把父进程的thread_info(进程描述结构)值复制给tsk的进程描述结构。然后将tsk的进程描述符中的task域改为tsk.
  
  [cpp]
  
  #define task_thread_info(task)  ((struct thread_info *)(task)->stack)
  
  static inline void setup_thread_stack(struct task_struct *p, struct task_struct *org)
  
  {
  
  *task_thread_info(p) = *task_thread_info(org);
  
  task_thread_info(p)->task = p;
  
  }
  
  在执行完setup_thread_stack之后,父子进程除了stack的指针之外是完全一样的。
  
  三,检查进程数创建限制
  
  [cpp]
  
  rt_mutex_init_task(p);//互斥锁初始化
  
  #ifdef CONFIG_TRACE_IRQFLAGS
  
  DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled);
  
  DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled);
  
  #endif
  
  retval = -EAGAIN;
  
  if (atomic_read(&p->user->processes) >=
  
  p->signal->rlim[RLIMIT_NPROC].rlim_cur) {
  
  if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) &&
  
  p->user != current->nsproxy->user_ns->root_user)
  
  goto bad_fork_free;
  
  }
  
  <span>  </span>atomic_inc(&p->user->__count);
  
  <span>  </span>atomic_inc(&p->user->processes);
  
  <span>  </span>get_group_info(p->group_info);增加组的使用计数
  
  进程结构task_struct中有一个域,名为:user_struct,这个域保存了当前用户的使用资源计数。
  
  [cpp]
  
  struct task_struct{
  
  ……
  
  struct user_struct *user;
  
  ……
  
  };
  
  在user_struct结构中包含processes表示当前的用户能够创建最多的进程数。如果超过限制,就放弃创建进程。root用户除外。如果没有超过限制,就将user_struct结构的引用计数加1,并将已经创建的进程数加1.
  
  四,线程检查
  
  检查线程创建是否超过最大限制,这个比较简单
  
  [cpp]
  
  /*
  
  * If multiple threads are within copy_process(), then this check
  
  * triggers too late. This doesn't hurt, the check is only there
  
  * to stop root fork bombs.
  
  */
  
  if (nr_threads >= max_threads)
  
  goto bad_fork_cleanup_count;
  
  五,写入数据
  
  在这里,进程描述符task_struct已经建立好了,其和父进程是一样的,除了栈地址不一样之外,现在开始修改一些值。
  
  [cpp]
  
  if (!try_module_get(task_thread_info(p)->exec_domain->module))
  
  goto bad_fork_cleanup_count;
  
  if (p->binfmt && !try_module_get(p->binfmt->module))
  
  goto bad_fork_cleanup_put_domain;
  
  p->did_exec = 0;当前还有加载任何执行的系统调用,所以为0以标识
  
  delayacct_tsk_init(p);  /* Must remain after dup_task_struct() */
  
  copy_flags(clone_flags, p);
  
  INIT_LIST_HEAD(&p->children);
  
  INIT_LIST_HEAD(&p->sibling);
  
  p->vfork_done = NULL;
  
  spin_lock_init(&p->alloc_lock);
  
  clear_tsk_thread_flag(p, TIF_SIGPENDING);
  
  init_sigpending(&p->pending);
  
  p->utime = cputime_zero;
  
  p->stime = cputime_zero;
  
  p->gtime = cputime_zero;
  
  p->utimescaled = cputime_zero;
  
  p->stimescaled = cputime_zero;
  
  p->prev_utime = cputime_zero;
  
  p->prev_stime = cputime_zero;
  
  #ifdef CONFIG_TASK_XACCT
  
  p->rchar = 0;        /* I/O counter: bytes read */
  
  p->wchar = 0;        /* I/O counter: bytes written */
  
  p->syscr = 0;        /* I/O counter: read syscalls */
  
  p->syscw = 0;        /* I/O counter: write syscalls */
  
  #endif
  
  task_io_accounting_init(p);
  
  acct_clear_integrals(p);
  
  p->it_virt_expires = cputime_zero;
  
  p->it_prof_expires = cputime_zero;
  
  p->it_sched_expires = 0;
  
  INIT_LIST_HEAD(&p->cpu_timers[0]);
  
  INIT_LIST_HEAD(&p->cpu_timers );
  
  INIT_LIST_HEAD(&p->cpu_timers );
  
  p->lock_depth = -1;      /* -1 = no lock */
  
  do_posix_clock_monotonic_gettime(&p->start_time);
  
  p->real_start_time = p->start_time;
  
  monotonic_to_bootbased(&p->real_start_time);
  
  #ifdef CONFIG_SECURITY
  
  p->security = NULL;
  
  #endif
  
  p->io_context = NULL;
  
  p->audit_context = NULL;
  
  cgroup_fork(p);
  
  #ifdef CONFIG_NUMA
  
  p->mempolicy = mpol_copy(p->mempolicy);
  
  if (IS_ERR(p->mempolicy)) {
  
  retval = PTR_ERR(p->mempolicy);
  
  p->mempolicy = NULL;
  
  goto bad_fork_cleanup_cgroup;
  
  }
  
  mpol_fix_fork_child_flag(p);
  
  #endif
  
  #ifdef CONFIG_TRACE_IRQFLAGS
  
  p->irq_events = 0;
  
  #ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
  
  p->hardirqs_enabled = 1;
  
  #else
  
  p->hardirqs_enabled = 0;
  
  #endif
  
  p->hardirq_enable_ip = 0;
  
  p->hardirq_enable_event = 0;
  
  p->hardirq_disable_ip = _THIS_IP_;
  
  p->hardirq_disable_event = 0;
  
  p->softirqs_enabled = 1;
  
  p->softirq_enable_ip = _THIS_IP_;
  
  p->softirq_enable_event = 0;
  
  p->softirq_disable_ip = 0;
  
  p->softirq_disable_event = 0;
  
  p->hardirq_context = 0;
  
  p->softirq_context = 0;
  
  #endif
  
  #ifdef CONFIG_LOCKDEP
  
  p->lockdep_depth = 0; /* no locks held yet */
  
  p->curr_chain_key = 0;
  
  p->lockdep_recursion = 0;
  
  #endif
  
  #ifdef CONFIG_DEBUG_MUTEXES
  
  p->blocked_on = NULL; /* not blocked yet */
  
  #endif
  
  这里是对一些值进行初始化,和各种策略相关的值,如调度等等,有些值是很重要的。
  
  六,加入调度
  
  [cpp]
  
  /* Perform scheduler related setup. Assign this task to a CPU. */
  
  sched_fork(p, clone_flags);
  
  这可以使用是进程可以参加调度,但此时进程的状态改为正在TASK_RUNNING,这以防止内核的其他部分将其改为可运行状态,因为我们对进程的设置还没有完成,这样调度进程会有问题。

            

首页 上一页 2 3 4 5 6 7 8 下一页 尾页 5/16/16
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C/C++学习指针一些事 下一篇C/C++学习之++i 和 i++..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: