OK6410A 开发板 (八) 18 linux-5.11 OK6410A start_kernel 功能角度 第二阶段之idle进程

发布者:雅致书香最新更新时间:2022-09-15 来源: csdn关键字:OK6410A  开发板  11  start_kernel 手机看文章 扫描二维码
随时随地手机看文章

idle 进程 相关的打印: 无

idle 进程相关的 函数

__mmap_switched 中的 ARM( ldmia   r4!, {r0, r1, sp} )

sched_init


idle 相关函数

start_kernel

sched_init

// 因为 1.__mmap_switched 中的 ARM( ldmia   r4!, {r0, r1, sp} )

// 因为 2.__mmap_switched_data 中的 .long   init_thread_union + THREAD_START_SP @ sp


/*


include/asm-generic/current.h

#define current get_current()

#define get_current() (current_thread_info()->task)


arch/arm/include/asm/thread_info.h

current_thread_info

return (struct thread_info *) (current_stack_pointer & ~(THREAD_SIZE - 1));



arch/arm/include/asm/percpu.h

register unsigned long current_stack_pointer asm ("sp");


*/


// current 等于 &init_task

// smp_processor_id() 等于 0 

init_idle(current, smp_processor_id()); 

// 用idle制作当前进程(current),并将 sched_class 设置为 idle_sched_class.启动时就能显示为...进程

// DECLARE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues);

// #define cpu_rq(cpu)     (&per_cpu(runqueues, (cpu)))

struct rq *rq = cpu_rq(cpu);


// 下面 idle 为 &init_task

__sched_fork(0, idle);

// 设置 tcb 中的 进程调度相关的成员

上锁

idle->state = TASK_RUNNING;

rq->idle = idle;

解锁


idle->sched_class = &idle_sched_class;


fork_init

// create a slab on which task_structs can be allocated

task_struct_cachep = kmem_cache_create_usercopy("task_struct"

// 设置最大进程数目

set_max_threads(MAX_THREADS);

// 将0号进程的task_t结构中的进程数资源限制的 当前值 设置为系统允许进程的一半

init_task.signal->rlim[RLIMIT_NPROC].rlim_cur = max_threads/2;

// 将0号进程的task_t结构中的进程数资源限制的 最大值 设置为系统允许进程的一半

// init_task.signal->rlim[RLIMIT_NPROC].rlim_max = max_threads/2;

arch_call_rest_init

rest_init

pid = kernel_thread(kernel_init, NULL, CLONE_FS);

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

cpu_startup_entry(CPUHP_ONLINE);



// 问题 : 从裸机 到 进程0 是什么时候开始,什么时候结束的

从 stext就开始了

到 start_kernel->rest_init->schedule_preempt_disabled -> schedule -> __schedule -> context_switch 结束

// 此时 cpu 就要执行 另一个进程了.

// 问题 : 创建进程0 的时候 init_task 是什么时候挂载到 strcuct rq 上的


早先版本中,idle是参与调度的,所以将其优先级设为最低,当没有其他进程可以运行时,才会调度执行 idle

而目前的版本中idle并不在运行队列中参与调度,而是在cpu全局运行队列rq中含idle指针,指向idle进程, 在调度器发现运行队列为空的时候运行, 调入运行

init_idle -> rq->idle = idle;


// 问题 : 创建进程0 的时候 怎么处理 入口函数的? 此时linux裸机已经在跑了,没有入口

idle 进程的建立的 过程 // 其实就是 init_task 结构体初始化的过程

1.sp 的初始化

// __mmap_switched -> ARM( ldmia   r4!, {r0, r1, sp} )

// __mmap_switched_data:

// .long   init_thread_union + THREAD_START_SP @ sp

// 在链接过程中确定了 一个值 (该值与 init_thread_union  相关)

// 将该值 写入 sp 中

// start_kernel 在 sp 对应的栈 中运行

2.TCB(init_task&init_thread_info)结构体的建立

// 静态创建的,不需要创建

// init_task&init_thread_info 是给 idle(一开始的裸机) 准备的 TCB

3.TCB(init_task&init_thread_info)结构体的定位

// idle 找到 为 它 准备的 TCB

// 根据current 找到该 裸机(后来的idle) 对应的结构体(init_task&init_thread_info)

// init_task  是 idle 进程的 信息1,供调度器(schedule)选择下一个进程用

// init_thread_info.cpu_context 是 idle进程的信息2,存储寄存器信息

4. init_idle:idle 进程的 信息1(init_task) 的初始化

//供 调度算法 选择 哪个进程 为 下一个进程

//5. kernel_thread/fork 的时候 建立了 其他(kenel_init) 进程

6. schedule:idle 进程的 信息2(init_thread_info.cpu_context) 的初始化

// 当前寄存器信息的保存

// idle调出 start_kernel->rest_init->schedule_preempt_disabled -> schedule -> __schedule -> context_switch

// 的时候 , 保存了 idle 的 各个寄存器 到  idle进程的信息2(init_thread_info.cpu_context)

// 这个过程是调度器的一部分,但是同时也是idle TCB 结构体初始化过程的一部分

7. 其他进程调用 schedule  , 选中 init_task 为 下一个 进程

// schedule -> __schedule -> pick_next_task

8. 将 init_task 对应的 init_thread_info.cpu_context 恢复到寄存器中

// idle调入 schedule -> __schedule -> context_switch

// 的时候 , 恢复了 idle进程的信息2(init_thread_info.cpu_context) 到 寄存器

// 此时,idle 重新执行


进程idle的建立

各个cpu 上0号进程 idle 的建立

创建过程

与cpu 的关系


cpu0 上的 idle进程

内核裸机程序(在 创建init 进程之前可以这么称呼吧) 在调用 sched_init 之后将自己变成了 0 号内核进程idle

// 这里要明白 裸机 和 进程的区别

// 进程比裸机 多了 以下内容

// 1.tcb,且 tcb的状态要设置好,其中 :  调度器要认识该tcb

// 2.进程代码运行的时候可以随时切出

// 那么 裸机切换到 进程(进程0)的时候,就需要做这些设置

// 什么时候能判断 该 idle0 创建成功了

// 0.current 能够索引当前的 tcb,start_kernel 刚进入时就已经能索引了(和__mmap_switched中赋值sp有关)

// 1.idle 又创建了一个线程A,idle 放弃cpu ,A开始正常运行,且能和idle进程正常调度

// 这就需要知道 调度器, 调度器 使用的 task_struct 序列

start_kernel -> sched_init 

-> init_idle(current, smp_processor_id());

-> __sched_fork(0, idle);

-> idle->state = TASK_RUNNING;

0号内核进程 在创建了init和kthreadd进程后, 调用cpu_idle()开始做idle循环

start_kernel -> arch_call_rest_init -> rest_init

-> cpu_startup_entry

-> do_idle

// 问题 : task_struct 结构体在哪里

// bootloader 转接给 kernel 之前 , 只有cpu0 在 跑 流程代码, 其他的cpu1...都是 halt 住的

cpu1 上的 idle 进程

cpu0 上的 init内核进程在演变成/sbin/init之前,会调用 smp_init(),让cpu1,cpu2 ... 开始启动

cpu1,cpu2 ... 启动过程中 会调用 如下函数,创建 对应cpu上的 idle进程

task = copy_process(CLONE_VM, 0, idle_regs(®s), 0, NULL, NULL, 0); 

init_idle(task, cpu);

从而创建 cpu1 上的 idle进程,cpu2 上的 idle进程, ...

    cpu0:smp_init

        idle_threads_init

            for_each_possible_cpu idle_init

                fork_idle

                    copy_process

        bringup_nonboot_cpus

            cpu_up

                _cpu_up

                    smp_ops.smp_boot_secondary(cpu, idle); / 即 psci_boot_secondary

                        psci_ops.cpu_on // 对应 0.1 版本的 psci为 psci_0_1_cpu_on

                            psci_0_1_cpu_on

                                __psci_cpu_on

                                    invoke_psci_fn // 调用什么 取决于 set_conduit 的设定值

                                        __invoke_psci_fn_smc

                                            arm_smccc_smc

                                                __arm_smccc_smc

                                                    SMCCC SMCCC_SMC

                                                        __SMC

                                                            0xE1600070 | (((imm4) & 0xF) << 0),

                                                            0xF7F08000 | (((imm4) & 0xF) << 16)


    cpu1:secondary_startup

        __secondary_switched

            secondary_start_kernel

                pr_debug("CPU%u: Booted secondary processorn", cpu);

                cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);

                do_idle


// 问题 : task_struct 结构体在哪里

//  作用是什么,为什么一个cpu上有一个


前两次调度时机

第一次调度时机

start_kernel->rest_init->schedule_preempt_disabled -> schedule -> __schedule -> context_switch


调度到了 kthreadd


第二次调度时机

kthreadd -> schedule -> __schedule -> context_switch

调度到了 kernel_init


idle 流程

idle 的流程

当需要调度时 , need_resched() 为 1

cpu_startup_entry

schedule_preempt_disabled

schedule

当不需要调度时, need_resched() 为 0


cpu_startup_entry

cpu_idle_loop

cpuidle_idle_call

arch_cpu_idle

cpu_do_idle

cpu_v7_do_idle

dsb

wfi

ret lr


什么时候设置的 need_resched

TODO


其他

thread->cpu_context

kernel_init : r4:0,r5:c0535d3c(kernel_init),pc:c010015c(ret_from_fork)

kthreadd : r4:0,r5:c012cc14(kthreadd),pc:c010015c(ret_from_fork)

--- 

idle

rest_init : r4:0,r5:0,pc:0

schedule_preempt_disabled -> schedule -> __schedule -> context_switch 中设置了 r4 r5 r6

do_idle : r4:c0e55d08(init_stack/init_thread_info/init_thread_union),r5:c0805980(init_task),pc:c0536778(__schedule中)


idle 堆栈

Freeing unused kernel memory: 1024K 前的堆栈

[14:57:54]CPU: 0 PID: 0 Comm: swapper Not tainted 5.11.0-00008-g0cf53aa024f-dirty #180

[14:57:54]Hardware name: SMDK6410

[14:57:54][] (unwind_backtrace) from [] (show_stack+0x10/0x14)

[14:57:54][] (show_stack) from [] (do_idle+0x8/0xd4)

[14:57:54][] (do_idle) from [] (cpu_startup_entry+0x10/0x14)

[14:57:54][] (cpu_startup_entry) from [] (start_kernel+0xbf4/0xe0c)

[14:57:54][] (start_kernel) from [<00000000>] (0x0)



Freeing unused kernel memory: 1024K 后的堆栈

[14:57:54]CPU: 0 PID: 0 Comm: swapper Not tainted 5.11.0-00008-g0cf53aa024f-dirty #180

[14:57:54]Hardware name: SMDK6410

[14:57:54][] (unwind_backtrace) from [] (show_stack+0x10/0x14)

[14:57:54][] (show_stack) from [] (do_idle+0x8/0xd4)

[14:57:54][] (do_idle) from [] (cpu_startup_entry+0x10/0x14)

[14:57:54][] (cpu_startup_entry) from [] (start_kernel+0xbf4/0xe0c)


kenel_init 堆栈

[14:57:47]CPU: 0 PID: 1 Comm: swapper Not tainted 5.11.0-00008-g0cf53aa024f-dirty #180

[14:57:47]Hardware name: SMDK6410

[1] [2]
关键字:OK6410A  开发板  11  start_kernel 引用地址:OK6410A 开发板 (八) 18 linux-5.11 OK6410A start_kernel 功能角度 第二阶段之idle进程

上一篇:OK6410A 开发板 (八) 19 linux-5.11 OK6410A start_kernel 功能角度 第三阶段之init进程
下一篇:OK6410A 开发板 (八) 17 linux-5.11 OK6410A start_kernel 功能角度 概览

推荐阅读最新更新时间:2024-10-12 20:07

基于MSP430F11X的低功耗低成本实时时钟
前言 实时时钟(RTC)可应用于多种领域--从钟表到时间标记事件,甚至到产生事件。对于通信工程、电力自动化、工业控制等自动化程度高的领域大多数情况下很多设备都处于无人值守的情况,都希望能把故障发生的时间和相关信息记录下来,以便具体分析。目前市面上有很多专用RTC器件,这些器件往往灵活性差,系统集成度低。而MSP430F11X系列单片机具有低成本、低电流损耗、使用灵活简单及扩展性好等优点,使之成为专用RTC器件在某些特殊场合的理想替代品。 本系统采用了TI公司超低功耗16位微处理器--MSP430F111,具有极低功耗特性、极强的抗干扰能力和极高的性价比。整个系统仅用两个普通电池(工作电压为3V)就可以长期工作,无需其他电源,
[单片机]
基于MSP430F<font color='red'>11</font>X的低功耗低成本实时时钟
贸泽抢先备货TI触摸传感LDC2114评估板
半导体与电子元器件分销商贸泽电子 (Mouser Electronics) 抢先备货Texas Instruments (TI) 用于LDC2112和LDC2114触摸传感解决方案的LDC2114评估模块 (EVM)。作为TI传感解决方案的新成员,LDC2114EVM可利用电感式传感技术来检测是否存在导电物体,充当电感式触摸按钮。LDC2114EVM内置的LDC2114为一款多通道低噪声电感数字转换器,并针对单片表面电感式触摸应用进行了优化。 电感式传感技术借助于测量导电物体的细微偏移,设计出金属、玻璃、塑料和木材等各种材质的触摸按钮。用于电感触摸系统的传感器线圈位于面板后部小型紧凑PCB面板上,并且不受周围环境影响。
[嵌入式]
贸泽抢先备货TI触摸传感LDC2<font color='red'>11</font>4评估板
iPhone 4S带头Q4 '11智能机出货量创新高
        全球智慧型手机在2011年第四季出货量爆增。市调机构IDC指出,由于苹果(Apple)iPhone 4S延迟推出,市场需求在长期压抑后蜂拥而出,再加上季节性需求强劲,让2011年第四季全球智慧型手机出货量上冲至一亿五千七百多万支,较2010年同期成长高达54%,并创下单季出货量最高的新纪录。       IDC资深市场分析师Ramon Llames表示,iPhone 4S无疑是扮演智慧型手机出货量成长的关键性角色;而其他品牌商为因应市场潮流,各式机种也相继问市,从而提升智慧型手机的整体出货量。至2011年第四季末,全球行动装置品牌商每出货三支手机,就有一支是智慧型手机。       由于苹果iPhone 4S
[手机便携]
中移动11月4日首发:回A股,募资560亿创纪录
10月29日晚,证监会发布公告称,中国移动将于11月4日首发上会。 此前8月18日,中国移动公布A股IPO招股书,拟于沪市主板上市,计划公开发行A股股份数量不超过9.65亿股,即不超过本次发行后公司已发行股份总数的4.50%(行使超额配售选择权之前),拟募集资金560亿元。 这将超过中国电信的542亿元,成为近10年来A股最高IPO募资额。 募集资金将分别用于5G精品网络建设项目、云资源新型基础设施建设项目、千兆智家建设项目、智慧中台建设项目、新一代信息技术研发、数智生态建设项目,总投资共1569亿元。 招股书还显示,中国移动5G网络总投资额将达983亿元,其中拟投入的募集资金金额为280亿元,占总额的一半。 今年前三季度,中国
[手机便携]
产业整合,2011年仅剩三家主力代工厂
据IHS iSuppli公司,到2011年末,可能只有三家代工厂商能够提供大批量、领先的半导体制造服务:台积电、GlobalFoundries Inc.和三星电子。 其它几家晶圆代工厂商,包括台联电和中芯国际,将能够提供接近领先水平的大批量制造服务,但上述三大代工厂商将是主力。 是否会有另一家厂商将加入进来?2011年非常有可能,英特尔可能决定利用自己的部分先进制造能力,向采用了Atom微处理器的设计公司和无厂半导体供应商提供代工服务。尽管这将代表英特尔的理念发生巨大变化,但它可能带来营业收入的明显增长和改善资产利用情况。向台积电及其客户提供Atom设计的策略,没有达到台积电及英特尔的期望。 到2011年末,
[半导体设计/制造]
产业整合,20<font color='red'>11</font>年仅剩三家主力代工厂
D类功放控制IC芯片LX1710/LX1711
摘要: LX1710/LX1711是Microsemi公司生产的一款数字功放控制器,它与外接功率型开关管配合可构成完整的数字功放,是中功率数字功放中具有Hi-Fi特性的控制芯片。文中介绍了它的要电气特性和外接电路,给出了它与仙童公司的MOSFET FDS4953及FDS6612A组成的数字功放评估板的应用电路和实际指标。 关键词: 中功率D类功放 数字功放控制IC LX1710 LX1711 FDS4953 FDS6612A 1 概述 D类数
[手机便携]
OK6410A 开发板 (三) 10 u-boot-2021.01 boot 解析 U-boot 镜像运行部分 cmdline
url : git@github.com:lisider/u-boot.git branch : ok6410a commit id : e63a4077ad3aea53107495b0b68b95e720fe6033 config : ok6410a_mini_defconfig // 涉及的 .S .s .c 文件 有 223个 reset arch/arm/cpu/arm1176/start.S 39 lowlevel_init(108) board/samsung/ok6410a/lowlevel_init.S 72 _main(110) arch/arm/lib/crt0.
[单片机]
博通Q1净利润1.9亿美元同比增117%
    北京时间4月24日早间消息,博通今天发布了2013财年第一财季财报。报告显示,博通第一财季净营收为20.1亿美元,比去年同期的18.3亿美元增长9.7%;净利润为1.91亿美元,比去年同期的8800万美元增长117%。博通第一财季业绩和第二财季业绩展望均超出华尔街分析师预期,推动其盘后股价上涨逾4%。   报告显示,博通第一财季净利润为1.91亿美元,每股收益33美分,这一业绩好于去年同期。2012财年第一财季,博通净利润为8800万美元,每股收益15美分。不计入一次性的特殊项目(不按照美国通用会计准则),博通第一财季调整后净利润为4亿美元,每股收益为65美分,超出分析师此前预期。财经信息供应商FactSet Researc
[手机便携]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved