do_fork
=>struct pid *pid = alloc_pid();
=>struct pid *pid = kmem_cache_alloc(pid_cachep, GFP_KERNEL);//分配pid结构体空间
=>nr = alloc_pidmap(current->nsproxy->pid_ns);//分配PID进程号
=>pid->nr = nr;//关联
=>for (type = 0; type < PIDTYPE_MAX; ++type)//初始化进程PID, PGID和SID私有hash表
==>INIT_HLIST_HEAD(&pid->tasks[type]);
=>hlist_add_head_rcu(&pid->pid_chain, &pid_hash[pid_hashfn(pid->nr)]);//将进程pid加入进程全局hash表
=>return pid;//返回pid结构体
=>p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr, pid);//拷贝父进程的东东到子进程
=>p = dup_task_struct(current);
=>struct task_struct *tsk = alloc_task_struct();
=>struct thread_info *ti = alloc_thread_info(tsk);
=>*tsk = *orig;//建立task_struct和thread_info的关系
tsk->stack = ti;
setup_thread_stack(tsk, orig);
=>retval = copy_files(clone_flags, p)//拷贝父进程的资源
retval = copy_fs(clone_flags, p)
retval = copy_sighand(clone_flags, p)
retval = copy_mm(clone_flags, p)
=>if (clone_flags & (CLONE_PARENT|CLONE_THREAD))//建立父子关系和伙伴关系列表
p->real_parent = current->real_parent;
else
p->real_parent = current;
p->parent = p->real_parent;
=>if (clone_flags & CLONE_THREAD)//如果是线程,则认祖归宗,找到组织
=>p->group_leader = current->group_leader;
=>list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group);//插入到领头线程的链表;新版本取消掉了TGID哈希表
=>if (likely(p->pid))
==>add_parent(p);
==>if (thread_group_leader(p))
p->signal->tty = current->signal->tty;
p->signal->pgrp = process_group(current);
set_signal_session(p->signal, process_session(current));
attach_pid(p, PIDTYPE_PGID, task_pgrp(current));//将P加入到当前进程的各种哈希链表中
=>struct pid_link *link;
link = &task->pids[type];
link->pid = pid;//指向领头进程的Pid
hlist_add_head_rcu(&link->node, &pid->tasks[type]);//加到领头进程的哈希表
attach_pid(p, PIDTYPE_SID, task_session(current));
list_add_tail_rcu(&p->tasks, &init_task.tasks);
==>attach_pid(p, PIDTYPE_PID, pid);
=>retval = copy_thread_tls(clone_flags, stack_start, stack_size, p, tls);
frame->ret_addr = (unsigned long) ret_from_fork; // 新进程的第一条指令
=>wake_up_new_task(p, clone_flags);//将新进程加到就绪队列,专门一章用来讲这个
=>return nr;//返回进行PID给应用层,PID结构体对应用层不可见
如果创建子进程,那么还有如下场景需要处理
if (clone_flags & CLONE_VFORK)//CLONE_VFORK代表创建子进程
wait_for_completion(&vfork);//等一下子进程
加载子进程会通过execve系统调用进行
.load_binary = load_aout_binary
=>retval = flush_old_exec(bprm);
=>retval = exec_mmap(bprm->mm);
=>mm_release(tsk, old_mm);
=>if (vfork_done) {
if (vfork_done) {
complete(vfork_done);//通知父进程可以继续进行
}
进程名在内核态如何获取,方法是 current->comm,作为字符串打印即可
参考文章:
进程创建之copy_process函数
https://blog.csdn.net/bullbat/article/details/7088484
[进程管理] copy_thread函数的一些不理解的地方,求助大家? 好文
http://bbs.chinaunix.net/thread-4180012-1-1.html
linux内核分析之fork()
https://www.cnblogs.com/qiuheng/p/5752284.html
Linux进程描述符task_struct结构体详解--Linux进程的管理与调度(一)
https://blog.csdn.net/gatieme/article/details/51383272