linux内核中两大重要的线程,migration_thread负责cpu的负载均衡(将进程从本地队列移动到目标cpu的队列),kthreadd负责为kthread_create_list链表中的成员创建内核线程。

内核版本2.6.24中的引导部分,start_kernel()->rest_init():

点击(此处)折叠或打开

static void noinline __init_refok rest_init(void)

__releases(kernel_lock)

{

int pid;

kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);

numa_default_policy();

pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);

kthreadd_task = find_task_by_pid(pid);

……

}

以上依次创建了kernel_init线程和kthreadd线程,rest_init()是在禁用抢占(preempt_disable)的情况下运行,因此保证了kernel_init()运行时kthreadd_task

已经指向ktheadd线程。

kernel_init()

调用do_pre_smp_initcalls()->migration_init();创建了负责将进程在cpu间移动(cpu负载均衡)的内

核线程migration_thread(每个cpu一个),创建线程是通过将包含待运行函数及参数的kthread_create_info结构挂入

kthread_create_list链表,然后唤醒kthreadd_task(即ktheadd线程),而ktheadd线程负责为链表上的每个结

构创建相应的线程。

点击(此处)折叠或打开

void __init migration_init(void)

{

void *cpu = (void *)(long)smp_processor_id();

int err;

/* Start

one for the boot

CPU: */

err = migration_call(&migration_notifier, CPU_UP_PREPARE, cpu);

BUG_ON(err == NOTIFY_BAD);

migration_call(&migration_notifier, CPU_ONLINE, cpu);

register_cpu_notifier(&migration_notifier);

}

首 先直接调用migration_call两次创建了引导cpu的migration_thread线程并唤醒,然后调用

register_cpu_notifier()将migration_notifier挂入cpu_chain链表,在之后

kernel_init()->smp_init()中将依次对其余未上线的cpu调用cpu_up()->_cpu_up(),该函数分别

以参数CPU_UP_PREPARE和CPU_ONLINE调用两次__raw_notifier_call_chain(),实则是运行

cpu_chain链表上的函数,也包括了migration_call(),因此其余cpu的migration_thread也得以创建,最终是每个

cpu上都有一个migration_thread线程。

点击(此处)折叠或打开

static int __cpuinit

_cpu_up(unsigned int cpu, int tasks_frozen)

{

int ret, nr_calls = 0;

void *hcpu = (void *)(long)cpu;

unsigned

long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0;

if (cpu_online(cpu) || !cpu_present(cpu))

return -EINVAL;

raw_notifier_call_chain(&cpu_chain, CPU_LOCK_ACQUIRE, hcpu);

ret = __raw_notifier_call_chain(&cpu_chain, CPU_UP_PREPARE | mod, hcpu,

-1, &nr_calls);

……

/* Now call notifier in preparation. */

raw_notifier_call_chain(&cpu_chain, CPU_ONLINE | mod, hcpu);

……

}

点击(此处)折叠或打开

static int __cpuinit

migration_call(struct

notifier_block *nfb, unsigned long

action, void *hcpu)

{

struct

task_struct *p;

int cpu = (long)hcpu;

unsigned

long flags;

struct

rq *rq;

switch (action) {

case CPU_LOCK_ACQUIRE:

mutex_lock(&sched_hotcpu_mutex);

break;

case CPU_UP_PREPARE:

case CPU_UP_PREPARE_FROZEN:

p = kthread_create(migration_thread, hcpu, "migration/%d", cpu);

if (IS_ERR(p))

return

NOTIFY_BAD;

kthread_bind(p, cpu);

/* Must

be high prio: stop_machine

expects to yield to it. */

rq = task_rq_lock(p, &flags);

__setscheduler(rq, p, SCHED_FIFO, MAX_RT_PRIO-1);

task_rq_unlock(rq, &flags);

cpu_rq(cpu)->migration_thread = p;

break;

case CPU_ONLINE:

case CPU_ONLINE_FROZEN:

/* Strictly

unnecessary, as first user

will wake it. */

wake_up_process(cpu_rq(cpu)->migration_thread);

break;

……

}

点击(此处)折叠或打开

struct task_struct *kthread_create(int (*threadfn)(void *data),

void *data,

const char

namefmt[],

...)

{

struct

kthread_create_info create;

create.threadfn = threadfn;

create.data = data;

init_completion(&create.started);

init_completion(&create.done);

spin_lock(&kthread_create_lock);

list_add_tail(&create.list, &kthread_create_list);

wake_up_process(kthreadd_task);

spin_unlock(&kthread_create_lock);

wait_for_completion(&create.done);

……

return

create.result;

}

linux 内核migration任务,[转]linux内核线程migration_thread和kthreadd的创建相关推荐

  1. Java线上问题排障:Linux内核bug引发JVM死锁导致线程假死

    Java本质上还是离不开操作系统,一来Java源码是用C/C++实现的,二来java进程还是需要依附于操作系统和硬件资源,有时候一些问题是操作系统级别导致的,下面的整个事件是源自一则真实的线上案例. ...

  2. linux用户空间和内核exit的语义--linux没有线程

    如果你在程序中调用了exit,那么很显然你的程序会退出,可是至于为何会退出那就是库的事情了,我为什么说只是库的事情而不关linux内核的事情呢?那是因为linux内核根本不管用户空间的行为策略.库的策 ...

  3. 实时Linux内核调度器 | Real-Time Linux Kernel Scheduler

    <Real-Time Linux Kernel Scheduler> HOWTOs by Ankita Garg on August 1, 2009 目录 Design Goal 设计目标 ...

  4. linux内核的进程管理,Linux内核设计与实现——进程管理

    主要内容 进程 进程描述符及任务结构 进程创建 线程在linux中的实现 进程终结 1. 进程 进程不仅仅是一段可执行程序代码,还包含其他资源,如打开的文件,挂起的信号,内核内部数据,处理器状态,一个 ...

  5. linux内核中启动页面,Linux内核启动过程分析

    下面给出内核映像完整的启动过程: arch/x86/boot/header.S: --->header第一部分(以前的bootsector.S):  载入bootloader到0x7c00处,设 ...

  6. 编译内核,busybox,dropbear组装linux小系统

    应用程序使用以下软件 busybox提供命令环境 dropbear提供ssh服务实现远程管理. 查看本物理机的硬件,来确认编译内核时选择相应的驱动.硬件信息获取方法: cat /proc/cpuinf ...

  7. deepin编译Linux内核,为Deepin编译Linux 5.10内核的悲伤故事经历:从入门到卸载

    简介 目的 解决Linux Deepin在更新内核到5.10后无法使用蓝牙的问题. 硬件:联想小新13 Pro 2020 AMD R5 4600U OS: win 10 + deepin 20 原因 ...

  8. Linux内核态之间进程通信,内核态和用户态通信(二)--实现

    本文主要使用netlink套接字实现中断环境与用户态进程通信. 系统环境:基于linux 2.6.32.27 和 linux 3.16.36 Linux内核态和用户态进程通信方法的提出和实现 用户上下 ...

  9. linux内核开发基础(linux内核源码、树莓派源码编译、SD卡挂载)

    首先下载树莓派linux内核源码: 下载网址:https://github.com/raspberrypi/linux 在树莓派使用指令:uname -r查看当前树莓派的版本号,然后选择对应的linu ...

  10. linux 内核空间 sy,在 Linux 下用户空间与内核空间数据交换的方式,第 1 部分: 内核启动参数、模块参数与sysf...

    级别: 初级 燚 杨 (), 计算机科学硕士 2006 年 2 月 16 日 本系列文章包括两篇,它们文详细地介绍了 Linux 系统下用户空间与内核空间数据交换的九种方式,包括内核启动参数.模块参数 ...

最新文章

  1. Linux下截屏方法!
  2. 省选专练[CQOI2007]涂色
  3. XCTF WEB cookie
  4. dede 验证码不显示 vdimgck.php,Dede后台验证码不显示解决方法详解(dedecms 5.7)
  5. 详细了解BGP—边界网关协议
  6. Angular应用启动时创建的injection token一览
  7. CentOS7+CDH5.14.0安装全流程记录,图文详解全程实测-8CDH5安装和集群配置
  8. 它身上的飞秋 战衣给他添上了英武的气势
  9. 沃尔沃汽车与高德合作:首款纯电动汽车XC40 RECHARGE采用高德方案
  10. 解决Winform应用程序中窗体背景闪烁的问题
  11. 偏微分方程的引入及概述
  12. mysql主从怎么确保数据一致_如何保证主从复制数据一致性
  13. 像素密度(衡量屏幕显示能力)
  14. 电脑32位和64位是什么
  15. am大学计算机科学,美国大学本科计算机科学专业排名一览
  16. Python分析并绘制可视化动态地图,实时查询全球疫情数据(11月最新...)
  17. 利用Python进行数据分析的学习笔记——chap9
  18. mysql怎么求方程的根_实验3-1 求一元二次方程的根
  19. iconfont-阿里图标库 的使用
  20. HTML5学习(三):布局标签、列表、超链接和id

热门文章

  1. 一张纸厚度是多少毫米_一张a4纸的厚度是多少mm
  2. 洛谷P2000 拯救世界(NTT+生成函数)
  3. numpy 之average
  4. html左边是菜单右边是内容,左首菜单栏右侧内容
  5. mysql中rpl_MySQL半同步复制之rpl_semi_sync_master_wait_point
  6. 几种常见电源防反接设计
  7. iPhone入门学习汇总
  8. 新加坡读计算机专业,【去新加坡读计算机专业】 - 环外新加坡留学网
  9. 【其他】计蒜客 ICPC Pacific Northwest Regional Contest 2017 Gym-101652X Star Arrangements
  10. CutefishOS 0.6 Beta 发布