深入linux内核架构--进程&线程

简介

进程和线程这两个词,每个程序员都十分熟悉,但是想要很清晰的描述出来却有一种不知道从何说起的感觉。所以今天结合一个具体的例子来描述一下进程与线程的相关概念:在terminal上敲出a.out这个自己编译出来可执行程序路径后,这个程序是怎么在linux系统中运行起来的?如果对于这个问题有兴趣的同学可以继续往下看。

对于linux内核下进程和线程的理解程度我经历过以下几个阶段:

  1. 知道进程和线程这两个基本概念:知道进程/线程相关的一些资源占用,调度的一些基本理论知识;知道进程=程序+数据等等;知道PC寄存器、指令、栈帧、上下文切换等一些零碎的概念。
  2. 知道进程和线程都是可独立调度的最小单位; 知道进程拥有独立地址空间,线程共享进程的地址空间,有自己独立的栈;知道pthread协议相关接口定义,以及会使用pthread接口创建线程/进程等操作。
  3. 知道线程在linux中本质上就是进程,可以分为内核线程,可调度线程和用户空间线程。内核线程是内核启动后的一些deamon线程用于处理一写内核状态工作,比如kswapd,flushd等;可调度线程是能够被内核调度感知的线程,也就是正常的native thread;用户空间线程不为内核调度感知,比如goroutine,gevent等,需要自己实现相关调度策略。
  4. 知道进程和线程在内核中是如何调度的:实时调度器,完全公平调度器等相关调度策略;知道可调度线程有内核栈和用户态栈两个不同的栈,当执行系统调用时需要从用户态栈切换到内核栈执行一些特权指令,比如write,mmap之类的。
  5. 知道在terminal bash中输入一个cmd之后,相关的进程是如何被操作系统运行起来的,知道线程是如何创建出来的。
  6. 知道栈中的指令是如何加载到CPU中,如何开始执行,上下文切换时的寄存器如何操作等。(这个阶段还没达到,不过不做内核开发的话,也没必要达到这个阶段。)

那么我们就通过结合linux源码以及一些man文档一起来深入了解一下进程和线程的实现,结合简介中说的例子来看一下linux用户进程及线程是如何被创建起来以及执行的。

【文章福利】小编推荐自己的Linux内核技术交流群:【977878001】整理一些个人觉得比较好得学习书籍、视频资料共享在群文件里面,有需要的可以自行添加哦!!!前100进群领取,额外赠送一份价值699的内核资料包(含视频教程、电子书、实战项目及代码)

内核资料直通车:Linux内核源码技术学习路线+视频教程代码资料

学习直通车:Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈

进程 & 线程

task_struct,mm_struct这两个数据结构,分别描述进程/线程的数据结构及进程虚拟地址空间,是内核管理的关键结构,下面是相关内核代码。

struct task_struct {
#ifdef CONFIG_THREAD_INFO_IN_TASK
    /*
     * For reasons of header soup (see current_thread_info()), this
     * must be the first element of task_struct.
     */
    struct thread_info      thread_info;
#endif
    /* -1 unrunnable, 0 runnable, >0 stopped: */
    volatile long           state;  // 运行状态

    void                *stack;  // 内核栈空间地址
    atomic_t            usage;
    /* Per task flags (PF_*), defined further below: */
    unsigned int            flags;
    unsigned int            ptrace; // 

#ifdef CONFIG_SMP  // 调度相关
    struct llist_node       wake_entry;
    int             on_cpu; // 是否已被分配到CPU上执行调度
#ifdef CONFIG_THREAD_INFO_IN_TASK
    /* Current CPU: */
    unsigned int            cpu; // 被分配到的CPU
...
#endif
// 调度相关
    int             on_rq; // 是否在runqueue队列中(就绪)
    int             prio; // 优先级
    int             static_prio; // 静态优先级
    int             normal_prio; // 普通优先级
    unsigned int            rt_priority; // 实时优先级
        // 上述优先级结合一个简单的算法来计算task_struct的权重,用于计算时间片 
    const struct sched_class    *sched_class; // 调度类,诸如实时调度,完全公平调度等
    struct sched_entity     se; // 关联到的调度实体,这是完全公平调度器真正调度的单位
    struct sched_rt_entity      rt; // 关联到的实时调度实体,这是实时调度器真正调度的单位
#ifdef CONFIG_CGROUP_SCHED
    struct task_group       *sched_task_group; // 组调度,cgroup相关
#endif
    struct sched_dl_entity      dl; // deadline调度器调度实体
...
    struct mm_struct        *mm; // 虚拟内存结构
    struct mm_struct        *active_mm;
...
    pid_t               pid;  // 进程id
    pid_t               tgid; // 组id

    /* Real parent process: */
    struct task_struct __rcu    *real_parent; // 真实的父进程(ptrace的时候需要用到)

    /* Recipient of SIGCHLD, wait4() reports: */
    struct task_struct __rcu    *parent; // 当前父进程

    /*
     * Children/sibling form the list of natural children:
     */
    struct list_head        children; // 子进程(当前进程fork出来的子进程/线程)
    struct list_head        sibling; // 兄弟进程
    struct task_struct      *group_leader;

    /*
     * 'ptraced' is the list of tasks this task is using ptrace() on.
     *
     * This includes both natural children and PTRACE_ATTACH targets.
     * 'ptrace_entry' is this task's link on the p->parent->ptraced list.
     */
    struct list_head        ptraced;
    struct list_head        ptrace_entry;

    /* PID/PID hash table linkage. */ //线程相关结构
    struct pid          *thread_pid;
    struct hlist_node       pid_links[PIDTYPE_MAX];
    struct list_head        thread_group;
    struct list_head        thread_node;

    struct completion       *vfork_done;

    /* CLONE_CHILD_SETTID: */
    int __user          *set_child_tid;

    /* CLONE_CHILD_CLEARTID: */
    int __user          *clear_child_tid;

    u64             utime; // 用户态运行时间
    u64             stime; // 和心态运行时间
...
    /* Context switch counts: */
    unsigned long           nvcsw; //自愿切换
    unsigned long           nivcsw; //非自愿切换

    /* Monotonic time in nsecs: */
    u64             start_time; // 创建时间

    /* Boot based time in nsecs: */
    u64             real_start_time; // 创建时间
    char                comm[TASK_COMM_LEN]; // 执行cmd名称,包括路径
    struct nameidata        *nameidata;  // 路径查找辅助结构
...
    /* Filesystem information: */
    struct fs_struct        *fs; // 文件系统信息,根路径及当前文件路径

    /* Open file information: */
    struct files_struct     *files; // 打开的文件句柄

    /* Namespaces: */
    struct nsproxy          *nsproxy; 

    /* Signal handlers: */
    struct signal_struct        *signal; // 信号量
    struct sighand_struct       *sighand; // 信号量处理函数
...
       /* CPU-specific state of this task: */
    struct thread_struct        thread; // 线程相关信息
};

struct mm_struct {
    struct {
                ... // 虚拟地址空间相关数据结构(虚拟地址空间比较复杂,这里不做过多介绍)
        unsigned long task_size;    /* size of task vm space: 
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
深入Linux内核架构与底层原理》是一本介绍Linux内核的经典书籍,主要围绕Linux内核的设计、架构和实现原理展开讲解。 该书首先介绍了Linux内核架构,包括进程管理、内存管理、文件系统、网络、设备驱动等方面。通过对Linux内核各个模块的功能和相互关系的剖析,读者可以对Linux内核的整体结构有一个全面的了解。 接着,书中详细讲解了Linux内核的底层原理。包括线程进程进程调度、内存管理、虚拟文件系统、网络协议栈、设备驱动等方面的内容。通过对这些底层原理的深入讲解,读者可以了解到Linux内核是如何实现这些功能的,并且能够更好地理解和分析Linux内核的代码。 此外,该书还着重介绍了Linux内核的设计哲学和设计思路。作者通过对多个实际案例的分析,向读者展示了Linux内核是如何通过简洁、灵活的设计和实现来提高性能和可扩展性的。这对于研究Linux内核的读者来说非常有价值,可以帮助他们更好地理解Linux内核的设计思想,从而更好地应用和开发Linux系统。 总之,《深入Linux内核架构与底层原理》是一本关于Linux内核深入研究的书籍,通过系统地介绍Linux内核架构和底层原理,帮助读者全面了解和理解Linux内核,并能够更好地应用和开发Linux系统。它不仅适合Linux内核的研究者和开发者阅读,也适合对Linux系统感兴趣的读者阅读。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值