文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

如何分析Linux内核源码do_fork

2023-06-16 14:36

关注

本篇文章为大家展示了如何分析Linux内核源码do_fork,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

我们都知道进程是Linux内核中最为重要的一个抽象概念,那么我们平时在fork一个进程时,该进程究竟是怎么产生的呢?

推送会浅谈一下在进程创建过程中扮演着重要角色的do_fork函数。

内核如何来抽象一个进程

内核通过一个叫做task_struct的结构体来抽象一个进程,该结构体的定义(以内核2.6为例)在include/linux.sched.h中。

截取部分task_struct如下:

如何分析Linux内核源码do_fork

上述task_struct属性是我节选出的部分其结构体中的属性,我们从中可以大致了解到标识一个进程的属性大致会有该用以表示该进程所处的状态,进程的标志,以及进程是否被其他进程跟踪,进程锁的深度,进程的优先级,进程的pid,进程的父母,进程的孩子链表,进程所打开的文件描述符表,进程所处的文件系统,进程的信号。。。。等等一堆我们平时可能遇到的和进程相关的东西。

do_fork简单分析 

接触linuxC编程的人都知道,创建一个进程我们需要调用fork函数,fork其实又是调用了clone函数来实现的,而clone函数中最关键的函数就是do_fork函数。

在分析do_fork前我们脑海中可以大致想象一下,进程究竟是如何被创建出来的,假如让你来创建一个进程你会咋么做?

我们可以这样去分析,既然原来的进程被抽象成一个task_struct,那么新进程也是一个task_struct只不过它里面的一些属性会不同与原来的task_struct,那么创建一个新进程所要做的工作就是赋值一个与原来进程一样都的task_struct结构,然后然后将新进程的task_struct不同于原来task_struct的属性进行修改即可。

do_fork定义在kernel/fork.c文件中。

在分析该函数之前我们先来分析一下它的函数的各个参数。

参数如下: 

如何分析Linux内核源码do_fork

clone_flags:该参数是此函数中最重要的一个参数,该值中的每个位都代表对子进程task_struct中的每种属性的设置;

stack_start:子进程用户态堆栈的开始地址;

regs:当系统发生系统调用时,需从用户态切换到内核态,此结构体用来保存此时用户态进程中的通用寄存器中的值,并被存放在内核态堆栈中;

stack_size:目前未被使用,通常设为0;

parent_tidptr:父进程在用户态下pid的地址;

child_tidptr:子进程在用户态下pid的地址;

其中clone_flags的标志位宏定义如下: 

如何分析Linux内核源码do_fork

举个简单的例子当我们的参数中设置了CLONE_VM这个宏,那么就以为这我们新创建的进程和其父进程要共享VM,当我们设置了CLONE_FILES时意味这父子进程之间共享打开的文件描述符。

do_fork开始执行后首先做的就是为子进程定义一个新的task_struct指针:

struct task_struct *p;

在下来会检查一些clone_flags所不允许的位组合,例如:

if (clone_flags & CLONE_NEWUSER) {  if (clone_flags & CLONE_THREAD)  return -EINVAL;  }

上述中不允许同时既设置了CLONE_NEWUSER标志,还设置CLONE_THREAD标志,这样就会产生错误。

类似上面当一系列的安全检查完毕之后,copy_process函数就登场了,copy_process函数工作流程具体如下:

1)调用dup_task_struct函数为新的进程创建一个内核栈,thread_info结构和task_struct等,当然此时的值都是和父进程完全一样的

dup_task_struct函数定义如下:

如何分析Linux内核源码do_fork

如何分析Linux内核源码do_fork

2)检查并确保新创建该子进程后,当前用户所拥有的进程数没有超出给它分配的资源限制,代码如下: 

如何分析Linux内核源码do_fork

3)子进程着手使自己与父进程区别开来,从父进程那继承过来的许多属性都要被清0或设置一个初始值,但task_struct中的大多数数据还是未被修改,部分代码如下:

如何分析Linux内核源码do_fork

如何分析Linux内核源码do_fork 

4)给子进程分配一个CPU,代码如下:

sched_fork(p, clone_flags);

5) 接着就是子进程拷贝父进程的一些资源,具体如下,调用copy_files函数拷贝父进程打开的文件描述符:  

如何分析Linux内核源码do_fork

调用copy_fs继承父进程所属的文件系统。 

如何分析Linux内核源码do_fork

调用copy_signal函数拷贝并设置新的signal_struct,signal_struct包含了大量的进程运行的信息,调用copy_mm函数处理与新进程的内存问题。 

如何分析Linux内核源码do_fork

调用copy_io函数拷贝父进程的I/O情况:

如何分析Linux内核源码do_fork 

还有调用copy_namespaces 和 copy_thread等,这里就不在赘述。

6)调用alloc_pid为新进程分配一个pid。

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

7)copy_process做一些收尾工作,并返回新进程的task_struct指针,此时再次回到了do_fork,新创建的子进程被唤醒,并让其先投入运行。

如何分析Linux内核源码do_fork 

总结

关于进程创建的源码理解,我感觉主要抓住俩点即可。***进程被内核抽象成了啥?它的数据结构是咋样的(task_struct)这点我们必须有所认识,第二创建进程最主要的其实就是拷贝父进程的task_struct里的属性,但是关键点是拷贝哪些,哪些又是子进程和父进程所不同的,很简单我们只需要把握住进程创建函数里的clone_flags参数就可以知道怎么拷贝了。

上述内容就是如何分析Linux内核源码do_fork,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-人工智能
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯