图说Linux进程之三

勿忘初心2018-11-27 11:18

此文已由作者刘超授权网易云社区发布。

欢迎访问网易云社区,了解更多网易技术产品运营经验。


五、计算机体系结构相关数据

在task_struct里面有一个thread_info





为什么需要单独的这个数据结构呢?因为不同的体系结构可能会有不同的实现。



从代码可以看出不同的体系结构有不同的实现。



在thread_info里面有一个指针指向task_struct。

这个指针有什么用的,当一个用户态的进程进入到内核的时候,如何找到对应的task_struct呢?

一般是从当前CPU的一个寄存器里面,通过函数current_thread_info得到在内核态里面的thread_info的地址,然后就可以通过指针找到task_struct了。


六、进程树


task_struct中有一系列指针是用来维护进程树的。


parent指向的是一个进程的原来的父进程,real_parent指向的是进程的当前的父进程,这两个值大多数情况下是一致的。

但是有一种情况下不一致,就是在一个进程被Debug的时候,这个时候GDB就变成了当前的父进程。


父进程有一个children指针指向子进程的列表,里面有两个指针,一个指头,一个指尾。

同一个层次的进程通过sibing链表串起来。


七、进程的资源管理


一个进程是一系列资源的集合,主要有哪些资源呢?


一个是files,指向这个进程打开的所有的文件,具体可参考Linux的虚拟文件系统VFS

一个是fs,指向文件系统相关的信息,例如进程的当前目录等,也可参考上面的那篇文章。

一个是sighand,指向用于处理信号的signal handler

一个是mm,指向这个进程的内存。


八、fork创建子进程



通过调用系统调用fork可以创建另一个进程。


会在内核里面调用_do_fork

里面会调用

p = copy_process(clone_flags, stack_start, stack_size, child_tidptr, NULL, trace, tls, NUMA_NO_NODE);



里面有

p = dup_task_struct(current, node);

retval = copy_creds(p, clone_flags);

cgroup_fork(p);

retval = copy_files(clone_flags, p);

retval = copy_fs(clone_flags, p);

retval = copy_sighand(clone_flags, p);

retval = copy_signal(clone_flags, p);

retval = copy_mm(clone_flags, p);

retval = copy_namespaces(clone_flags, p);

retval = copy_io(clone_flags, p);

retval = copy_thread_tls(clone_flags, stack_start, stack_size, p, tls);

pid = alloc_pid(p->nsproxy->pid_ns_for_children);

子进程有独立的task_struct结构,有自己的PID,在fork的当下,代码段是和父进程是一样的,一般会被exec系列函数重新加载新的代码段,数据段和栈是新创建的,采取的copy on write的模式。

上面提到的四个数据结构,都是完全拷贝一份的。


九、pthread_create创建新线程


新的线程和原来的线程是共享进程空间的,因而调用__clone函数。

在内核中调用sys_clone函数,但是会设定以下的flag

CLONE_VM,则子线程和父线程共享虚拟内存

CLONE_FILES,共享files

CLONE_FS,共享fs

CLONE_SIGHAND,共享sighand。



免费领取验证码、内容安全、短信发送、直播点播体验包及云服务器等套餐

更多网易技术、产品、运营经验分享请点击