美文网首页
Linux内核设计与实现 进程管理2:进程、线程创建

Linux内核设计与实现 进程管理2:进程、线程创建

作者: 虹桥过夜好无聊 | 来源:发表于2017-12-21 21:17 被阅读0次

    进程与线程的关系

        在Linux中,没有线程这个概念。内核将线程与进程一视同仁,也就是说线程相当于一个标准的进程,在调度时不使用特殊策略。同时,内核也不为线程维护多余的数据结构。换句话说,在Linux中,线程仅仅是一个与其他进程分享某些相同资源,地址空间的进程。相比于Windows有很大的不同。

        在Windows中,线程显示地被视为轻量进程(lightweight processes)。换句话说,在类似于Windows这样明显区分线程与进程的系统中,我们必须在进程描述符里维护特别的数据结构,指向它的不同线程,并且标记出如打开文件表,地址空间这类的共享资源。这是一种累赘。但是在Linux中,由于理念的不同,我们简单地为每个线程维护一个task_struct即可。

        但是,进程和线程的创建是不一样的。都调用了clone(),而参数不同。

    创建进程

        在Unix和Linux系统中,我们用fork()和exec*()来创建新的进程。如果进程的数据太大,那么在fork()复制进程地址空间这个动作时,将会耗费大量的时间。特别是当fork()之后立即调用exec*()函数,加载一个新的可执行程序,这样的时间开销就显得更加没有意义。所以采用写时复制(Copy-on-Write)机制。就是说,父子进程以只读的方式共享地址空间段,直到其中某一方进行写操作,改变了既有数据。采用COW机制,那么当一个进程fork()之后立即调用exec*()时,开销就只剩下 1.为子进程复制父进程的页表。 2.为子进程创建进程描述符。

        fork()实现是通过调用clone()这个系统调用,clone()接受一系列的标志作为参数,这些标志决定了在父子进程中共享哪些信息。与fork()相同,vfork()和__clone()都使用了该系统调用,区别在与传递的参数。所以重点在与clone()如何工作。

        首先clone()调用do_fork(),在<kernel/fork.c>中,下图为其参数列表。

do_fork()

       在检测了是否进行ptrace之后,do_fork()调用了copy_process()拷贝一份当前进程的样本,copy_process()函数接受传递给clone()的clone_flags标志,当前进程的起始地址,regs参数(未知用途),进程栈大小等参数,并返回一个task_struct类型的指针。

调用copy_process()

    在copy_process()中检测传递的clone_flags是否符合标准,检测子进程数目是否超过系统限制的数目,当前用户进程数是否大于系统限制,更新相关数据。并完成其他工作,其中包括调用dup_task_struct()创建子进程的内核栈,以及为子进程创建新的task_struct和thread_info结构。

dup_task_struct()

    然后copy_process()为新进程初始化task_struct中的各项数据,包括分配PID,设置状态为TASK_UNINTERRUPTIBLE, 根据clone_flags设置相关共享信息等等。

copy_process() 1 copy_process() 2

    当copy_process()执行成功后,返回do_fork()中,最终返回子进程的PID。子进程创建工作完毕。

 创建线程

    线程的创建就如同普通任务的创建一样,都是调用clone()函数,只不过传递相应的flags参数。

    对于普通的fork()相当于使用:

                    clone(CLONE_VM | CONE_FS | CLONE_FILES | CLONE_SIGHAND, 0);

                    clone(SIGCHLD, 0);

    而对于vfork():

                    clone(CLONE_VFORK | CLONE_VM | SIGCHLD, 0);

    可用的clone()的flags值在<linux/sched.h>中。

   内核线程

        内核线程只能由另一内核线程产生。调用基于clone()的kernel_thread()函数。类似于应用进程创建线程函数,fn指向期望新内核线程一直执行的函数,arg用来为该函数传递参数。

                    int Kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);

相关文章

  • Linux内核设计与实现 进程管理2:进程、线程创建

    进程与线程的关系 在Linux中,没有线程这个概念。内核将线程与进程一视同仁,也就是说线程相当于一个标准的...

  • 开题

    linux 内核 线程和进程管理

  • Linux 线程

    Linux支持内核线程,用户进程以及LWP,Linux2.6之后支持线程组概念。 内核线程是内核创建的线程,处理内...

  • 2.进程管理

    进程管理 进程是操作系统的基本概念,本节主要总结Linux内核如何管理进程:进程在内核中如何创建,消亡。 1.进程...

  • 进程和计划任务详解(一)

    学习内容: 1、进程相关知识(用户空间、内核空间、进程创建、进程优先级、进程内存)2、Linux进程查看及管理工具...

  • Linux中进程的概念

    一直不大了解进程和线程之间的区别,最近看书《Linux内核设计与实现》,里面有说到进程的概念,下面就把原文给抄...

  • 0.Unix程序运行准备

    前言 在学习了《Linux内核设计与实现》之后,对于Linux的内核的原理有了一定认识,尤其是进程管理,地址空间等...

  • 孤儿进程、僵尸进程和守护进程

    [TOC] 参考资料 Linux 之守护进程、僵死进程与孤儿进程【概述】-Linux内核三驾马车之-进程管理【Li...

  • Linux内核线程kernel thread详解

    内核线程 为什么需要内核线程 Linux内核可以看作一个服务进程(管理软硬件资源,响应用户进程的种种合理以及不合理...

  • 实验四【2021OS】

    实验四:LINUX进程与磁盘管理 创建进程,查看进程,杀死进程。查看磁盘使用,挂载。 创建进程 fork() 首先...

网友评论

      本文标题:Linux内核设计与实现 进程管理2:进程、线程创建

      本文链接:https://www.haomeiwen.com/subject/cuxzwxtx.html