copy_process函数在进程创建的do_fork函数中调用,主要完成进程数据结构,各种资源的初始化。初始化方式可以重新分配,也可以共享父进程资源,主要根据传入CLONE参数来确定。
-
-
-
-
-
-
-
-
- static struct task_struct *copy_process(unsigned long clone_flags,
- unsigned long stack_start,
- struct pt_regs *regs,
- unsigned long stack_size,
- int __user *child_tidptr,
- struct pid *pid,
- int trace)
- {
- int retval;
- struct task_struct *p;
- int cgroup_callbacks_done = 0;
-
- if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
- return ERR_PTR(-EINVAL);
-
-
-
-
-
- if ((clone_flags & CLONE_THREAD) && !(clone_flags & CLONE_SIGHAND))
- return ERR_PTR(-EINVAL);
-
-
-
-
-
-
- if ((clone_flags & CLONE_SIGHAND) && !(clone_flags & CLONE_VM))
- return ERR_PTR(-EINVAL);
-
-
-
-
-
-
-
- if ((clone_flags & CLONE_PARENT) &&
- current->signal->flags & SIGNAL_UNKILLABLE)
- return ERR_PTR(-EINVAL);
-
-
-
-
- retval = security_task_create(clone_flags);
- if (retval)
- goto fork_out;
-
- retval = -ENOMEM;
-
-
-
-
-
- p = dup_task_struct(current);
- if (!p)
- goto fork_out;
-
-
- ftrace_graph_init_task(p);
-
- rt_mutex_init_task(p);
-
- #ifdef CONFIG_PROVE_LOCKING/*not set*/
- DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled);
- DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled);
- #endif
- retval = -EAGAIN;
-
-
-
-
-
-
- if (atomic_read(&p->real_cred->user->processes) >=
- p->signal->rlim[RLIMIT_NPROC].rlim_cur) {
- if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) &&
- p->real_cred->user != INIT_USER)
- goto bad_fork_free;
- }
-
- retval = copy_creds(p, clone_flags);
- if (retval < 0)
- goto bad_fork_free;
-
-
-
-
-
-
- retval = -EAGAIN;
-
- if (nr_threads >= max_threads)
- goto bad_fork_cleanup_count;
-
- if (!try_module_get(task_thread_info(p)->exec_domain->module))
- goto bad_fork_cleanup_count;
-
- p->did_exec = 0;
- delayacct_tsk_init(p);
-
- copy_flags(clone_flags, p);
- INIT_LIST_HEAD(&p->children);
- INIT_LIST_HEAD(&p->sibling);
- rcu_copy_process(p);
- p->vfork_done = NULL;
- spin_lock_init(&p->alloc_lock);
-
- 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;
-
- p->default_timer_slack_ns = current->timer_slack_ns;
-
- task_io_accounting_init(&p->ioac);
- acct_clear_integrals(p);
-
- posix_cpu_timers_init(p);
-
- p->lock_depth = -1;
- do_posix_clock_monotonic_gettime(&p->start_time);
- p->real_start_time = p->start_time;
- monotonic_to_bootbased(&p->real_start_time);
- p->io_context = NULL;
- p->audit_context = NULL;
- cgroup_fork(p);
- #ifdef CONFIG_NUMA/*not set*/
- p->mempolicy = mpol_dup(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/*yes*/
- p->irq_events = 0;
- #ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW/*not found*/
- 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/*yes*/
- p->lockdep_depth = 0;
- p->curr_chain_key = 0;
- p->lockdep_recursion = 0;
- #endif
-
- #ifdef CONFIG_DEBUG_MUTEXES/*not set */
- p->blocked_on = NULL;
- #endif
-
- p->bts = NULL;
-
- p->stack_start = stack_start;
-
-
- sched_fork(p, clone_flags);
-
-
-
- retval = perf_event_init_task(p);
- if (retval)
- goto bad_fork_cleanup_policy;
-
- if ((retval = audit_alloc(p)))
- goto bad_fork_cleanup_policy;
-
-
-
-
- if ((retval = copy_semundo(clone_flags, p)))
- goto bad_fork_cleanup_audit;
- if ((retval = copy_files(clone_flags, p)))
- goto bad_fork_cleanup_semundo;
- if ((retval = copy_fs(clone_flags, p)))
- goto bad_fork_cleanup_files;
- if ((retval = copy_sighand(clone_flags, p)))
- goto bad_fork_cleanup_fs;
- if ((retval = copy_signal(clone_flags, p)))
- goto bad_fork_cleanup_sighand;
- if ((retval = copy_mm(clone_flags, p)))
- goto bad_fork_cleanup_signal;
- if ((retval = copy_namespaces(clone_flags, p)))
- goto bad_fork_cleanup_mm;
- if ((retval = copy_io(clone_flags, p)))
- goto bad_fork_cleanup_namespaces;
- retval = copy_thread(clone_flags, stack_start, stack_size, p, regs);
- if (retval)
- goto bad_fork_cleanup_io;
-
- if (pid != &init_struct_pid) {
- retval = -ENOMEM;
- pid = alloc_pid(p->nsproxy->pid_ns);
- if (!pid)
- goto bad_fork_cleanup_io;
-
- if (clone_flags & CLONE_NEWPID) {
- retval = pid_ns_prepare_proc(p->nsproxy->pid_ns);
- if (retval < 0)
- goto bad_fork_free_pid;
- }
- }
-
- p->pid = pid_nr(pid);
- p->tgid = p->pid;
-
-
-
-
- if (clone_flags & CLONE_THREAD)
- p->tgid = current->tgid;
-
- if (current->nsproxy != p->nsproxy) {
- retval = ns_cgroup_clone(p, pid);
- if (retval)
- goto bad_fork_free_pid;
- }
-
- p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
-
-
-
- p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr: NULL;
- #ifdef CONFIG_FUTEX/*yes*/
- p->robust_list = NULL;
- #ifdef CONFIG_COMPAT/*not found*/
- p->compat_robust_list = NULL;
- #endif
- INIT_LIST_HEAD(&p->pi_state_list);
- p->pi_state_cache = NULL;
- #endif
-
-
-
- if ((clone_flags & (CLONE_VM|CLONE_VFORK)) == CLONE_VM)
- p->sas_ss_sp = p->sas_ss_size = 0;
-
-
-
-
-
- clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE);
- #ifdef TIF_SYSCALL_EMU/*not found*/
- clear_tsk_thread_flag(p, TIF_SYSCALL_EMU);
- #endif
- clear_all_latency_tracing(p);
-
-
- p->exit_signal = (clone_flags & CLONE_THREAD) ? -1 : (clone_flags & CSIGNAL);
- p->pdeath_signal = 0;
- p->exit_state = 0;
-
-
-
-
-
- p->group_leader = p;
- INIT_LIST_HEAD(&p->thread_group);
-
-
-
-
- cgroup_fork_callbacks(p);
- cgroup_callbacks_done = 1;
-
-
- write_lock_irq(&tasklist_lock);
-
-
-
-
-
-
-
-
-
-
- p->cpus_allowed = current->cpus_allowed;
- p->rt.nr_cpus_allowed = current->rt.nr_cpus_allowed;
- if (unlikely(!cpu_isset(task_cpu(p), p->cpus_allowed) ||
- !cpu_online(task_cpu(p))))
- set_task_cpu(p, smp_processor_id());
-
-
-
-
- if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) {
- p->real_parent = current->real_parent;
- p->parent_exec_id = current->parent_exec_id;
- } else {
- p->real_parent = current;
- p->parent_exec_id = current->self_exec_id;
- }
-
- spin_lock(¤t->sighand->siglock);
-
-
-
-
-
-
-
-
-
- recalc_sigpending();
- if (signal_pending(current)) {
- spin_unlock(¤t->sighand->siglock);
- write_unlock_irq(&tasklist_lock);
- retval = -ERESTARTNOINTR;
- goto bad_fork_free_pid;
- }
-
- if (clone_flags & CLONE_THREAD) {
- atomic_inc(¤t->signal->count);
- atomic_inc(¤t->signal->live);
- p->group_leader = current->group_leader;
-
- list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group);
- }
-
- if (likely(p->pid)) {
-
- list_add_tail(&p->sibling, &p->real_parent->children);
-
- tracehook_finish_clone(p, clone_flags, trace);
-
- if (thread_group_leader(p)) {
- if (clone_flags & CLONE_NEWPID)
-
-
-
- p->nsproxy->pid_ns->child_reaper = p;
-
- p->signal->leader_pid = pid;
- tty_kref_put(p->signal->tty);
- p->signal->tty = tty_kref_get(current->signal->tty);
-
-
- attach_pid(p, PIDTYPE_PGID, task_pgrp(current));
- attach_pid(p, PIDTYPE_SID, task_session(current));
- list_add_tail_rcu(&p->tasks, &init_task.tasks);
- __get_cpu_var(process_counts)++;
- }
- attach_pid(p, PIDTYPE_PID, pid);
- nr_threads++;
- }
-
- total_forks++;
- spin_unlock(¤t->sighand->siglock);
- write_unlock_irq(&tasklist_lock);
- proc_fork_connector(p);
-
- cgroup_post_fork(p);
- perf_event_fork(p);
- return p;
-
- bad_fork_free_pid:
- if (pid != &init_struct_pid)
- free_pid(pid);
- bad_fork_cleanup_io:
- put_io_context(p->io_context);
- bad_fork_cleanup_namespaces:
- exit_task_namespaces(p);
- bad_fork_cleanup_mm:
- if (p->mm)
- mmput(p->mm);
- bad_fork_cleanup_signal:
- if (!(clone_flags & CLONE_THREAD))
- __cleanup_signal(p->signal);
- bad_fork_cleanup_sighand:
- __cleanup_sighand(p->sighand);
- bad_fork_cleanup_fs:
- exit_fs(p);
- bad_fork_cleanup_files:
- exit_files(p);
- bad_fork_cleanup_semundo:
- exit_sem(p);
- bad_fork_cleanup_audit:
- audit_free(p);
- bad_fork_cleanup_policy:
- perf_event_free_task(p);
- #ifdef CONFIG_NUMA
- mpol_put(p->mempolicy);
- bad_fork_cleanup_cgroup:
- #endif
- cgroup_exit(p, cgroup_callbacks_done);
- delayacct_tsk_free(p);
- module_put(task_thread_info(p)->exec_domain->module);
- bad_fork_cleanup_count:
- atomic_dec(&p->cred->user->processes);
- exit_creds(p);
- bad_fork_free:
- free_task(p);
- fork_out:
- return ERR_PTR(retval);
- }
- static struct task_struct *dup_task_struct(struct task_struct *orig)
- {
- struct task_struct *tsk;
- struct thread_info *ti;
- unsigned long *stackend;
-
- int err;
-
- prepare_to_copy(orig);
-
- tsk = alloc_task_struct();
- if (!tsk)
- return NULL;
-
- ti = alloc_thread_info(tsk);
- if (!ti) {
- free_task_struct(tsk);
- return NULL;
- }
-
- err = arch_dup_task_struct(tsk, orig);
- if (err)
- goto out;
-
- tsk->stack = ti;
-
- err = prop_local_init_single(&tsk->dirties);
- if (err)
- goto out;
-
- setup_thread_stack(tsk, orig);
- stackend = end_of_stack(tsk);
-
- *stackend = STACK_END_MAGIC;
-
- #ifdef CONFIG_CC_STACKPROTECTOR/*yes*/
- tsk->stack_canary = get_random_int();
- #endif
-
-
- atomic_set(&tsk->usage,2);
- atomic_set(&tsk->fs_excl, 0);
- #ifdef CONFIG_BLK_DEV_IO_TRACE/*yes*/
- tsk->btrace_seq = 0;
- #endif
- tsk->splice_pipe = NULL;
-
- account_kernel_stack(ti, 1);
-
- return tsk;
-
- out:
- free_thread_info(ti);
- free_task_struct(tsk);
- return NULL;
- }
-
-
-
- void sched_fork(struct task_struct *p, int clone_flags)
- {
- int cpu = get_cpu();
-
- __sched_fork(p);
-
-
-
-
- if (unlikely(p->sched_reset_on_fork)) {
- if (p->policy == SCHED_FIFO || p->policy == SCHED_RR) {
- p->policy = SCHED_NORMAL;
- p->normal_prio = p->static_prio;
- }
-
- if (PRIO_TO_NICE(p->static_prio) < 0) {
- p->static_prio = NICE_TO_PRIO(0);
- p->normal_prio = p->static_prio;
- set_load_weight(p);
- }
-
-
-
-
-
- p->sched_reset_on_fork = 0;
- }
-
-
-
-
- p->prio = current->normal_prio;
-
- if (!rt_prio(p->prio))
- p->sched_class = &fair_sched_class;
-
- #ifdef CONFIG_SMP
- cpu = p->sched_class->select_task_rq(p, SD_BALANCE_FORK, 0);
- #endif
- set_task_cpu(p, cpu);
-
- #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)/*yes*/
- if (likely(sched_info_on()))
- memset(&p->sched_info, 0, sizeof(p->sched_info));
- #endif
- #if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW)
- p->oncpu = 0;
- #endif
- #ifdef CONFIG_PREEMPT/*not set*/
-
- task_thread_info(p)->preempt_count = 1;
- #endif
- plist_node_init(&p->pushable_tasks, MAX_PRIO);
-
- put_cpu();
- }
主要调用__sched_fork
- /*
- * Perform scheduler related setup for a newly forked process p.
- * p is forked by current.
- *
- * __sched_fork() is basic setup used by init_idle() too:
- */
- static void __sched_fork(struct task_struct *p)
- { /*初始化调度实体*/
- p->se.exec_start = 0;
- p->se.sum_exec_runtime = 0;
- ...
-
- p->se.nr_wakeups_idle = 0;
-
- #endif
-
- INIT_LIST_HEAD(&p->rt.run_list);/*初始化实时调度运行队列*/
- p->se.on_rq = 0;
- INIT_LIST_HEAD(&p->se.group_node);
-
- #ifdef CONFIG_PREEMPT_NOTIFIERS/*yes*/
- INIT_HLIST_HEAD(&p->preempt_notifiers);
- #endif
-
- /*
- * We mark the process as running here, but have not actually
- * inserted it onto the runqueue yet. This guarantees that
- * nobody will actually run it, and a signal or other external
- * event cannot wake it up and insert it on the runqueue either.
- *//*英文注释写的很清楚了*/
- p->state = TASK_RUNNING;
- }
注释了大部分,有很多地方是很容易看懂的。另外对于进程创建,不用版本的内核差别很大,所以如果是看这块,最好先确定具体的版本,新版本中可能会加入很多新的东西。这样,需结合其他机制来理解。
阅读(1929) | 评论(0) | 转发(0) |