smp_init过程解析
当你看到这样的log,会不会很慌张?

竟然由CPU没有启动成功,除了什么故障?
本文将结合我遇到的一个问题,将启动过程中bringup secondary cpu的过程分析一下。
smp_init代码如下:
602 void __init smp_init(void)
603 {
604 int num_nodes, num_cpus;
605 unsigned int cpu;
606
607 idle_threads_init();
608 cpuhp_threads_init();
609
610 pr_info("====cpuhp-walk:Bringing up secondary CPUs ...\n");
611
612 /* FIXME: This should be done in userspace --RR */
613 for_each_present_cpu(cpu) {
614 if (num_online_cpus() >= setup_max_cpus)
615 break;
616 pr_info("====cpuhp-walk:before bringing up cpu:%d\n", cpu);
617 if (!cpu_online(cpu))
618 cpu_up(cpu);
619 pr_info("====cpuhp-walk:after bringing up cpu:%d\n", cpu);
620 }
621
622 num_nodes = num_online_nodes();
623 num_cpus = num_online_cpus();
624 pr_info("====cpuhp-walk:Brought up %d node%s, %d CPU%s\n",
625 num_nodes, (num_nodes > 1 ? "s" : ""),
626 num_cpus, (num_cpus > 1 ? "s" : ""));
627
628 /* Any cleanup work */
629 smp_cpus_done(setup_max_cpus);
630 }
可以看得出在smp_init中,cpu0依次调用cpu_up启动其他的cpu,启动完成一个,再启动下一个,直到所有cpu都启动完毕,才继续内核剩余的启动流程,整个过程从smp_init开始,从smp_init结束。
下面分析具体的过程,我们将启动其他cpu成为BP(boot cpu),将被启动的cpu成为AP(不知道A表示哪个单词):
BP AP
smp_init | do_cpu_up| --> cpuhp_invoke_callback| --> smpboot_create_threads| perf_event_init_cpu| workqueue_prepare_cpu| hrtimers_prepare_cpu| ...| bringup_cpu| -->__cpu_up| -->boot_secondary (cpu_ops[cpu]->cpu_boot(cpu))| --> cpu_psci_cpu_boot| -->psci_cpu_on (invoke_psci_fn(0xc4000003, cpuid, secondary_entry, 0);)| secondary_entrynext cpu --> secondary_startup| --> __secondary_switched| -->secondary_start_kernel | --> notify_cpu_starting| -->cpuhp_invoke_callback| -->sched_cpu_starting| gic_starting_cpu| arch_timer_starting_cpu| dummy_timer_starting_cpu| | bringup_wait_for_ap可以看出,BP通过bringup_cpu函数,调用psci的函数,请求firmware启动AP,然后原地等待AP启动的结果。
firmware给AP上电之后,AP进入head.S中的secondary_entry,然后进入secondary_start_kernel,完成一系列回调之后,通知BP自己启动成功。BP从bringup_wait_for_ap返回,继续启动下一个cpu。
在cpuhp_invoke_callback所调用的回调函数的定义在这:
kernel/cpu.c1426 /* Boot processor state steps */
1427 static struct cpuhp_step cpuhp_hp_states[] = {
1428 [CPUHP_OFFLINE] = {
1429 .name = "offline",
1430 .startup.single = NULL,
1431 .teardown.single = NULL,
1432 },
1433 #ifdef CONFIG_SMP
1434 [CPUHP_CREATE_THREADS]= {
1435 .name = "threads:prepare",
1436 .startup.single = smpboot_create_threads,
1437 .teardown.single = NULL,
1438 .cant_stop = true,
1439 },
1440 [CPUHP_PERF_PREPARE] = {
1441 .name = "perf:prepare",
1442 .startup.single = perf_event_init_cpu,
1443 .teardown.single = perf_event_exit_cpu,
1444 },
1445 [CPUHP_WORKQUEUE_PREP] = {
1446 .name = "workqueue:prepare",
1447 .startup.single = workqueue_prepare_cpu,
1448 .teardown.single = NULL,
1449 },
1450 [CPUHP_HRTIMERS_PREPARE] = {
1451 .name = "hrtimers:prepare",
1452 .startup.single = hrtimers_prepare_cpu,
1453 .teardown.single = hrtimers_dead_cpu,
1454 },
1455 [CPUHP_SMPCFD_PREPARE] = {
1456 .name = "smpcfd:prepare",
1457 .startup.single = smpcfd_prepare_cpu,
1458 .teardown.single = smpcfd_dead_cpu,
1459 },
1460 [CPUHP_RELAY_PREPARE] = {
1461 .name = "relay:prepare",
1462 .startup.single = relay_prepare_cpu,
1463 .teardown.single = NULL,
1464 },
1465 [CPUHP_SLAB_PREPARE] = {
1466 .name = "slab:prepare",
1467 .startup.single = slab_prepare_cpu,
1468 .teardown.single = slab_dead_cpu,
1469 },
1470 [CPUHP_RCUTREE_PREP] = {
1471 .name = "RCU/tree:prepare",
...
1485 /* Kicks the plugged cpu into life */
1486 [CPUHP_BRINGUP_CPU] = {
1487 .name = "cpu:bringup",
1488 .startup.single = bringup_cpu,
1489 .teardown.single = NULL,
1490 .cant_stop = true,
1491 },
1492 /* Final state before CPU kills itself */
1493 [CPUHP_AP_IDLE_DEAD] = {
1494 .name = "idle:dead",
1495 },
1496 /*
1497 * Last state before CPU enters the idle loop to die. Transient state
1498 * for synchronization.
1499 */
1500 [CPUHP_AP_OFFLINE] = {
1501 .name = "ap:offline",
1502 .cant_stop = true,
1503 },
1504 /* First state is scheduler control. Interrupts are disabled */
1505 [CPUHP_AP_SCHED_STARTING] = {
1506 .name = "sched:starting",
1507 .startup.single = sched_cpu_starting,
1508 .teardown.single = sched_cpu_dying,
1509 },
1510 [CPUHP_AP_RCUTREE_DYING] = {
1511 .name = "RCU/tree:dying",
1512 .startup.single = NULL,
1513 .teardown.single = rcutree_dying_cpu,
1514 },
1515 [CPUHP_AP_SMPCFD_DYING] = {
1516 .name = "smpcfd:dying",
1517 .startup.single = NULL,
1518 .teardown.single = smpcfd_dying_cpu,
1519 },
1520 /* Entry state on starting. Interrupts enabled from here on. Transient
1521 * state for synchronsization */
1522 [CPUHP_AP_ONLINE] = {
1523 .name = "ap:online",
1524 },
1525 /*
1526 * Handled on controll processor until the plugged processor manages
1527 * this itself.
1528 */
1529 [CPUHP_TEARDOWN_CPU] = {
1530 .name = "cpu:teardown",
1531 .startup.single = NULL,
...
1535 /* Handle smpboot threads park/unpark */
1536 [CPUHP_AP_SMPBOOT_THREADS] = {
1537 .name = "smpboot/threads:online",
1538 .startup.single = smpboot_unpark_threads,
1539 .teardown.single = smpboot_park_threads,
1540 },
1541 [CPUHP_AP_IRQ_AFFINITY_ONLINE] = {
1542 .name = "irq/affinity:online",
1543 .startup.single = irq_affinity_online_cpu,
1544 .teardown.single = NULL,
1545 },
1546 [CPUHP_AP_PERF_ONLINE] = {
1547 .name = "perf:online",
1548 .startup.single = perf_event_init_cpu,
1549 .teardown.single = perf_event_exit_cpu,
1550 },
1551 [CPUHP_AP_WATCHDOG_ONLINE] = {
1552 .name = "lockup_detector:online",
1553 .startup.single = lockup_detector_online_cpu,
1554 .teardown.single = lockup_detector_offline_cpu,
1555 },
1556 [CPUHP_AP_WORKQUEUE_ONLINE] = {
1557 .name = "workqueue:online",
1558 .startup.single = workqueue_online_cpu,
1559 .teardown.single = workqueue_offline_cpu,
1560 },
1561 [CPUHP_AP_RCUTREE_ONLINE] = {
1562 .name = "RCU/tree:online",
1563 .startup.single = rcutree_online_cpu,
1564 .teardown.single = rcutree_offline_cpu,
1565 },
1566 #endif
1567 /*
1568 * The dynamically registered state space is here
1569 */
1570
1571 #ifdef CONFIG_SMP
1572 /* Last state is scheduler control setting the cpu active */
1573 [CPUHP_AP_ACTIVE] = {
1574 .name = "sched:active",
1575 .startup.single = sched_cpu_activate,
1576 .teardown.single = sched_cpu_deactivate,
1577 },
1578 #endif
1579
1580 /* CPU is fully up and running. */
1581 [CPUHP_ONLINE] = {
1582 .name = "online",
1583 .startup.single = NULL,
1584 .teardown.single = NULL,
1585 },
1586 };1482,3-9 60所有的回调函数一次调用,最重要的是bringup_cpu,这个是通过firmware直接给cpu上电启动的过程。
psci通过设备树节点获取与固件通信的方法(method:smc),smc具体的操作指令,可以在include/uapi/linux/psci.h中查找.
我在代码中增加一些打印语句,完整的smp_init的过程如下:
[ 0.064050] smp: ====cpuhp-walk:Bringing up secondary CPUs ...
[ 0.064051] smp: ====cpuhp-walk:before bringing up cpu:0
[ 0.064052] smp: ====cpuhp-walk:after bringing up cpu:0
[ 0.064053] smp: ====cpuhp-walk:before bringing up cpu:1
[ 0.064053] cpuhp_walk:cpu:1,do_cpu_up
[ 0.064060] cphp_walk:cpu:1,cpuhp_up_callbacks
[ 0.064061] cphp_walk:cpu:1,cpuhp_invoke_callback, 1.1, cb:smpboot_create_threads+0x0/0xe0
[ 0.104074] cphp_walk:cpu:1,cpuhp_invoke_callback, 1.1, cb:perf_event_init_cpu+0x0/0x140
[ 0.104080] cphp_walk:cpu:1,cpuhp_invoke_callback, 1.1, cb:workqueue_prepare_cpu+0x0/0x98
[ 0.112080] cphp_walk:cpu:1,cpuhp_invoke_callback, 1.1, cb:hrtimers_prepare_cpu+0x0/0xb0
[ 0.112084] cphp_walk:cpu:1,cpuhp_invoke_callback, 1.1, cb:smpcfd_prepare_cpu+0x0/0x70
[ 0.112089] cphp_walk:cpu:1,cpuhp_invoke_callback, 1.1, cb:relay_prepare_cpu+0x0/0xf8
[ 0.112092] cphp_walk:cpu:1,cpuhp_invoke_callback, 1.1, cb:rcutree_prepare_cpu+0x0/0x1c0
[ 0.112099] cphp_walk:cpu:1,cpuhp_invoke_callback, 1.1, cb:timers_prepare_cpu+0x0/0x80
[ 0.112101] cphp_walk:cpu:1,cpuhp_invoke_callback, 1.1, cb:bringup_cpu+0x0/0x140
[ 0.112104] cpuhp_walk:cpu:1,bringup_cpu
[ 0.112105] cpuhp_walk:cpu:1,__cpu_up
[ 0.112106] cpuhp_walk:cpu:1,boot_secondary, cpu_boot:cpu_psci_cpu_boot+0x0/0x94
[ 0.112109] psci: cpuhp_walk:cpu:1,cpu_psci_cpu_boot, cpu_on:psci_cpu_on+0x0/0x94
[ 0.112112] psci: cphp_walk:cpuid:1,psci_cpu_on, fn:0xc4000003
[ 0.145924] cphp_walk:cpu:1,secondary_start_kernel
[ 0.145934] Detected PIPT I-cache on CPU1
[ 0.145942] cpuhp_walk:cpu:1,notify_cpu_starting
[ 0.145943] cphp_walk:cpu:1,cpuhp_invoke_callback, 1.1, cb:sched_cpu_starting+0x0/0x120
[ 0.145946] cphp_walk:cpu:1,cpuhp_invoke_callback, 1.1, cb:gic_starting_cpu+0x0/0x40
[ 0.145950] GICv3: CPU1: found redistributor 1 region 1:0x00000000299a0000
[ 0.145958] GICv3: CPU1: using allocated LPI pending table @0x0000002176620000
[ 0.145964] cphp_walk:cpu:1,cpuhp_invoke_callback, 1.1, cb:arch_timer_starting_cpu+0x0/0x318
[ 0.145971] cphp_walk:cpu:1,cpuhp_invoke_callback, 1.1, cb:dummy_timer_starting_cpu+0x0/0x88
[ 0.145973] cpuhp_walk, CPU1: Booted secondary processor 0x0000000001 [0x701f6633]
[ 0.145978] cpuhp_walk:cpu:1,bringup_cpu, wait ap
[ 0.145980] cphp_walk:cpu:1,bringup_wait_for_ap, 1
[ 0.145984] cphp_walk:cpu:1,bringup_wait_for_ap, 2
[ 0.145987] cphp_walk:cpu:1,cpuhp_invoke_callback, 1.1, cb:smpboot_unpark_threads+0x0/0xb0
[ 0.145994] cphp_walk:cpu:1,cpuhp_invoke_callback, 1.1, cb:irq_affinity_online_cpu+0x0/0x110
[ 0.145998] cphp_walk:cpu:1,cpuhp_invoke_callback, 1.1, cb:perf_event_init_cpu+0x0/0x140
[ 0.146002] cphp_walk:cpu:1,cpuhp_invoke_callback, 1.1, cb:workqueue_online_cpu+0x0/0x228
[ 0.146019] cphp_walk:cpu:1,cpuhp_invoke_callback, 1.1, cb:rcutree_online_cpu+0x0/0x98
[ 0.146022] cphp_walk:cpu:1,cpuhp_invoke_callback, 1.1, cb:page_writeback_cpu_online+0x0/0x20
[ 0.146025] cphp_walk:cpu:1,cpuhp_invoke_callback, 1.1, cb:vmstat_cpu_online+0x0/0x70
[ 0.146029] cphp_walk:cpu:1,cpuhp_invoke_callback, 1.1, cb:sched_cpu_activate+0x0/0x168
[ 0.146035] smp: ====cpuhp-walk:after bringing up cpu:1
[ 0.146036] smp: ====cpuhp-walk:before bringing up cpu:2
[ 0.146037] cpuhp_walk:cpu:2,do_cpu_up
[ 0.146041] cphp_walk:cpu:2,cpuhp_up_callbacks
[ 0.146042] cphp_walk:cpu:2,cpuhp_invoke_callback, 1.1, cb:smpboot_create_threads+0x0/0xe0
[ 0.185939] cphp_walk:cpu:2,cpuhp_invoke_callback, 1.1, cb:perf_event_init_cpu+0x0/0x140
[ 0.185943] cphp_walk:cpu:2,cpuhp_invoke_callback, 1.1, cb:workqueue_prepare_cpu+0x0/0x98
[ 0.193946] cphp_walk:cpu:2,cpuhp_invoke_callback, 1.1, cb:hrtimers_prepare_cpu+0x0/0xb0
[ 0.193949] cphp_walk:cpu:2,cpuhp_invoke_callback, 1.1, cb:smpcfd_prepare_cpu+0x0/0x70
[ 0.193952] cphp_walk:cpu:2,cpuhp_invoke_callback, 1.1, cb:relay_prepare_cpu+0x0/0xf8
[ 0.193954] cphp_walk:cpu:2,cpuhp_invoke_callback, 1.1, cb:rcutree_prepare_cpu+0x0/0x1c0
[ 0.193959] cphp_walk:cpu:2,cpuhp_invoke_callback, 1.1, cb:timers_prepare_cpu+0x0/0x80
[ 0.193961] cphp_walk:cpu:2,cpuhp_invoke_callback, 1.1, cb:bringup_cpu+0x0/0x140
[ 0.193964] cpuhp_walk:cpu:2,bringup_cpu
[ 0.193964] cpuhp_walk:cpu:2,__cpu_up
[ 0.193965] cpuhp_walk:cpu:2,boot_secondary, cpu_boot:cpu_psci_cpu_boot+0x0/0x94
[ 0.193967] psci: cpuhp_walk:cpu:2,cpu_psci_cpu_boot, cpu_on:psci_cpu_on+0x0/0x94
[ 0.193969] psci: cphp_walk:cpuid:256,psci_cpu_on, fn:0xc4000003
[ 0.227952] cphp_walk:cpu:2,secondary_start_kernel
[ 0.227961] Detected PIPT I-cache on CPU2
[ 0.227967] cpuhp_walk:cpu:2,notify_cpu_starting
[ 0.227968] cphp_walk:cpu:2,cpuhp_invoke_callback, 1.1, cb:sched_cpu_starting+0x0/0x120
[ 0.227972] cphp_walk:cpu:2,cpuhp_invoke_callback, 1.1, cb:gic_starting_cpu+0x0/0x40
[ 0.227976] GICv3: CPU2: found redistributor 100 region 2:0x00000000299c0000
[ 0.227994] GICv3: CPU2: using allocated LPI pending table @0x0000002176630000
[ 0.227999] cphp_walk:cpu:2,cpuhp_invoke_callback, 1.1, cb:arch_timer_starting_cpu+0x0/0x318
[ 0.228007] cphp_walk:cpu:2,cpuhp_invoke_callback, 1.1, cb:dummy_timer_starting_cpu+0x0/0x88
[ 0.228010] cpuhp_walk, CPU2: Booted secondary processor 0x0000000100 [0x701f6633]
[ 0.228017] cpuhp_walk:cpu:2,bringup_cpu, wait ap
[ 0.228019] cphp_walk:cpu:2,bringup_wait_for_ap, 1
[ 0.228022] cphp_walk:cpu:2,bringup_wait_for_ap, 2
[ 0.228029] cphp_walk:cpu:2,cpuhp_invoke_callback, 1.1, cb:smpboot_unpark_threads+0x0/0xb0
[ 0.228039] cphp_walk:cpu:2,cpuhp_invoke_callback, 1.1, cb:irq_affinity_online_cpu+0x0/0x110
[ 0.228042] cphp_walk:cpu:2,cpuhp_invoke_callback, 1.1, cb:perf_event_init_cpu+0x0/0x140
[ 0.228047] cphp_walk:cpu:2,cpuhp_invoke_callback, 1.1, cb:workqueue_online_cpu+0x0/0x228
[ 0.228070] cphp_walk:cpu:2,cpuhp_invoke_callback, 1.1, cb:rcutree_online_cpu+0x0/0x98
[ 0.228073] cphp_walk:cpu:2,cpuhp_invoke_callback, 1.1, cb:page_writeback_cpu_online+0x0/0x20
[ 0.228076] cphp_walk:cpu:2,cpuhp_invoke_callback, 1.1, cb:vmstat_cpu_online+0x0/0x70
[ 0.228080] cphp_walk:cpu:2,cpuhp_invoke_callback, 1.1, cb:sched_cpu_activate+0x0/0x168
[ 0.228086] smp: ====cpuhp-walk:after bringing up cpu:2
[ 0.228087] smp: ====cpuhp-walk:before bringing up cpu:3
[ 0.228088] cpuhp_walk:cpu:3,do_cpu_up
[ 0.228092] cphp_walk:cpu:3,cpuhp_up_callbacks
[ 0.228093] cphp_walk:cpu:3,cpuhp_invoke_callback, 1.1, cb:smpboot_create_threads+0x0/0xe0
[ 0.267968] cphp_walk:cpu:3,cpuhp_invoke_callback, 1.1, cb:perf_event_init_cpu+0x0/0x140
[ 0.267972] cphp_walk:cpu:3,cpuhp_invoke_callback, 1.1, cb:workqueue_prepare_cpu+0x0/0x98
[ 0.275974] cphp_walk:cpu:3,cpuhp_invoke_callback, 1.1, cb:hrtimers_prepare_cpu+0x0/0xb0
[ 0.275977] cphp_walk:cpu:3,cpuhp_invoke_callback, 1.1, cb:smpcfd_prepare_cpu+0x0/0x70
[ 0.275980] cphp_walk:cpu:3,cpuhp_invoke_callback, 1.1, cb:relay_prepare_cpu+0x0/0xf8
[ 0.275983] cphp_walk:cpu:3,cpuhp_invoke_callback, 1.1, cb:rcutree_prepare_cpu+0x0/0x1c0
[ 0.275988] cphp_walk:cpu:3,cpuhp_invoke_callback, 1.1, cb:timers_prepare_cpu+0x0/0x80
[ 0.275990] cphp_walk:cpu:3,cpuhp_invoke_callback, 1.1, cb:bringup_cpu+0x0/0x140
[ 0.275993] cpuhp_walk:cpu:3,bringup_cpu
[ 0.275994] cpuhp_walk:cpu:3,__cpu_up
[ 0.275995] cpuhp_walk:cpu:3,boot_secondary, cpu_boot:cpu_psci_cpu_boot+0x0/0x94
[ 0.275996] psci: cpuhp_walk:cpu:3,cpu_psci_cpu_boot, cpu_on:psci_cpu_on+0x0/0x94
[ 0.275998] psci: cphp_walk:cpuid:257,psci_cpu_on, fn:0xc4000003
[ 0.309980] cphp_walk:cpu:3,secondary_start_kernel
[ 0.309985] Detected PIPT I-cache on CPU3
[ 0.309989] cpuhp_walk:cpu:3,notify_cpu_starting
[ 0.309990] cphp_walk:cpu:3,cpuhp_invoke_callback, 1.1, cb:sched_cpu_starting+0x0/0x120
[ 0.309993] cphp_walk:cpu:3,cpuhp_invoke_callback, 1.1, cb:gic_starting_cpu+0x0/0x40
[ 0.309996] GICv3: CPU3: found redistributor 101 region 3:0x00000000299e0000
[ 0.310002] GICv3: CPU3: using allocated LPI pending table @0x0000002176640000
[ 0.310007] cphp_walk:cpu:3,cpuhp_invoke_callback, 1.1, cb:arch_timer_starting_cpu+0x0/0x318
[ 0.310012] cphp_walk:cpu:3,cpuhp_invoke_callback, 1.1, cb:dummy_timer_starting_cpu+0x0/0x88
[ 0.310014] cpuhp_walk, CPU3: Booted secondary processor 0x0000000101 [0x701f6633]
[ 0.310019] cpuhp_walk:cpu:3,bringup_cpu, wait ap
[ 0.310021] cphp_walk:cpu:3,bringup_wait_for_ap, 1
[ 0.310024] cphp_walk:cpu:3,bringup_wait_for_ap, 2
[ 0.310028] cphp_walk:cpu:3,cpuhp_invoke_callback, 1.1, cb:smpboot_unpark_threads+0x0/0xb0
[ 0.310036] cphp_walk:cpu:3,cpuhp_invoke_callback, 1.1, cb:irq_affinity_online_cpu+0x0/0x110
[ 0.310039] cphp_walk:cpu:3,cpuhp_invoke_callback, 1.1, cb:perf_event_init_cpu+0x0/0x140
[ 0.310043] cphp_walk:cpu:3,cpuhp_invoke_callback, 1.1, cb:workqueue_online_cpu+0x0/0x228
[ 0.310050] cphp_walk:cpu:3,cpuhp_invoke_callback, 1.1, cb:rcutree_online_cpu+0x0/0x98
[ 0.310052] cphp_walk:cpu:3,cpuhp_invoke_callback, 1.1, cb:page_writeback_cpu_online+0x0/0x20
[ 0.310054] cphp_walk:cpu:3,cpuhp_invoke_callback, 1.1, cb:vmstat_cpu_online+0x0/0x70
[ 0.310057] cphp_walk:cpu:3,cpuhp_invoke_callback, 1.1, cb:sched_cpu_activate+0x0/0x168
[ 0.310063] smp: ====cpuhp-walk:after bringing up cpu:3
[ 0.310064] smp: ====cpuhp-walk:Brought up 1 node, 4 CPUs
[ 0.310066] SMP: Total of 4 processors activated.
[ 0.310067] CPU features: detected: 32-bit EL0 Support
[ 0.310069] CPU features: detected: CRC32 instructions
[ 0.310303] CPU: All CPU(s) started at EL2经查,是CPU厂商firmware的问题, 也就是psci_cpu_on, fn:0xc4000003的问题。
所以以后遇到这样的问题,熟悉了过程,就不慌了。
本文的psci部分由我的同事提供,同时,在阅读和分析代码之前,我还参照了如下链接的信息:
https://www.cnblogs.com/pengdonglin137/p/11925299.html
https://zhuanlan.zhihu.com/p/538782115
https://blog.csdn.net/weixin_45264425/article/details/127895018
https://zhuanlan.zhihu.com/p/545550388
此外,由于功耗控制的原因,系统运行期间,还会通过cpu idle来间断的关闭和打开cpu,也就是cpu hotplug,打开cpu的操作和上述过程相同,关闭cpu的过程与cpu up相反,读者自行阅读代码,也是通过psci来关闭cpu。
相关文章:
smp_init过程解析
当你看到这样的log,会不会很慌张?竟然由CPU没有启动成功,除了什么故障?本文将结合我遇到的一个问题,将启动过程中bringup secondary cpu的过程分析一下。smp_init代码如下:602 void __init smp_init(void) …...
判断推理之逻辑判断
考点一翻译推理(一)题目特征题干或选项中出现多组“逻辑关联词”,如:“如果……那么……”、“只要……就……”、“只有……才……”、“所有”、“有些”、“……且……”、“ ……或……”等典型逻辑关联词。(二&am…...
2023金三银四常见Handler面试总结,附带答案
以下的Handler的面试题都是在面试过程中总结出来比较常见的面试题,现在分享给大家,希望可以帮助你们!1.Handler的实现原理从四个方面看Handler、Message、MessageQueue 和 Looper Handler:负责消息的发送和处理 Message:消息对象,…...
为什么机器人操作系统ROS1、ROS2这么难学
AI回复:ROS1、ROS2是机器人操作系统,涉及到很多复杂的概念和技术,需要有一定的编程和机器人知识基础才能学习。此外,ROS1和ROS2的架构和设计也有很大的不同,需要花费一定的时间和精力去学习和适应。但是,一…...
day01
授课老师 :陶国荣 联系方式 : taogrtedu.cn 授课阶段 : Web前端基础 授课内容 : HTML CSS JavaScript 文章目录一、讲师和课程介绍二、Web前端介绍1. 什么是网页2. 网页的组成3. 网页的优势4. 开发前的准备三、 HTML语法介绍…...
第四十章 linux-并发解决方法五(顺序锁seqlock)
第四十章 linux-并发解决方法四(顺序锁seqlock) 文章目录第四十章 linux-并发解决方法四(顺序锁seqlock)顺序锁的设计思想是,对某一共享数据读取时不加锁,写的时候加锁。为了保证读取的过程中不会因为写入名…...
【SPSS】交叉设计方差分析和协方差分析详细操作教程(附案例实战)
🤵♂️ 个人主页:@艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞👍🏻 收藏 📂加关注+ 目录 方差分析概述 交叉设计方差分析...
playwright--核心概念和Selector定位
文章目录前言一、浏览器二、浏览器上下文三、页面和框架四、Selectors1、data-test-id selector2、CSS and XPath selector3、text 文本selector4、id定位selector5、Selector 组合定位五、内置Selector前言 Playwright提供了一组API可自动化操作Chromium,Firefox和…...
响应式操作实战案例
Project Reactor 框架 在Spring Boot 项目 Maven 中添加依赖管理。 <dependency><groupId>io.projectreactor</groupId><artifactId>reactor-core</artifactId> </dependency><dependency><groupId>io.projectreactor</g…...
NetApp AFF A900:针对任务关键型应用程序的解决方案
NetApp AFF A900:适用于数据中心的解决方案 AFF A 系列中的 AFF A900 高端 NVMe 闪存存储功能强大、安全可靠、具有故障恢复能力,提供您为任务关键型企业级应用程序提供动力并保持数据始终可用且安全所需的一切。 AFF A900:针对任务关键型应…...
使用Houdini输出四面体网格并输出tetgen格式
我们的目标是从houdini输出生成的四面体,希望是tetgen格式的。 众所周知,houdini是不能直接输出四面体的。 有三方案去解决: 输出点云ply文件,然后利用tetgen生成网格。输出Hounidi内置的.geo格式文件,然后写个脚本…...
组合预测 | MATLAB实现EMD-KPCA-LSTM、EMD-LSTM、LSTM多输入单输出回归预测对比
组合预测 | MATLAB实现EMD-KPCA-LSTM、EMD-LSTM、LSTM多输入单输出回归预测对比 目录 组合预测 | MATLAB实现EMD-KPCA-LSTM、EMD-LSTM、LSTM多输入单输出回归预测对比预测效果基本介绍模型描述程序设计参考资料预测效果 基本介绍 MATLAB实现EMD-KP...
【C语言】操作符详解总结(万字)
操作符详解1. 操作符分类2. 算术操作符3. 移位操作符3.1 整数的二进制是怎么形成的3.2 左移操作符3.3 右移操作符4. 位操作符5. 赋值操作符6. 单目操作符6.1 单目操作符介绍6.2 sizeof 和 数组7. 关系操作符8. 逻辑操作符9. 条件操作符9.1 练习19.2 练习210. 逗号表达式11. 下标…...
mac系统手册(帮助/说明)
文章目录1. mac自带的帮助文档2. Mac使用技巧(提示)2.1 聚焦搜索2.2 截图(录制屏幕)2.3 调出右键菜单2.4 快速查看2.5 翻译2.5.1 词典解释2.5.2 翻译(字、词和句)3. macOS使用手册3.1 在聚焦中进行计算和转…...
VLC播放器Demo(录像,截图等功能),Android播放器Demo可二次开发。
VLC播放器Demo(录像,截图等功能),可二次开发。 GitHub地址:https://github.com/ILoveLin/VlcRecordPlayer GitHub地址:https://github.com/ILoveLin/VlcRecordPlayer GitHub地址:https://github.com/ILoveLin/VlcRecordPlayer …...
WeSpeaker支持C++部署链路
WeSpeaker正式更新C部署链路,推理引擎使用OnnxRuntime,支持从语音中提取Speaker Embedding信息,代码详见WeSpeaker/runtime[1]。 Libtorch和onnx的选择? Speaker Embedding提取任务流程简单,并且声纹模型(如ResNet\E…...
window vscode编辑appsmith源码
前言 本来最开始用的idea打开wsl中的appsmith,卡得一批。最后没办法,用自己的电脑装成ubuntu server,然后vscode的远程开发对appsmith源码进行编辑。如果自己电脑内存16个G或者更大可能打开wsl中的估计会还好,我公司电脑只有8g所…...
操作系统面试题
操作系统一、简介篇1.解释一下什么是操作系统2.操作系统的主要功能3.软件访问硬件的几种方式4.操作系统的主要目的是什么5.为什么Linux系统下的应用程序不能直接在Windows下运行6.什么是用户态和内核态7.用户态和内核态如何切换8.什么是内核二、进程和线程篇1.多处理系统的优势…...
Kafka入门(七)
下面聊聊Kafka的配置参数,包括生产者的配置参数、Broker的配置参数、消费者的配置参数。 1、生产者配置参数 acks 该参数控制了生产者的消息发送确认机制,用于指定分区中必须有多少个副本成功接收到消息后生产者才会认为这条消息写入是成功的,…...
微服务介绍
微服务 微服务架构发展 微服务这个概念最早是在2011年5月威尼斯的一个软件架构会议上讨论提出的,用于描述一些作为通用架构风格的设计原则;2012年3月在波兰举行的Degree Conference大会,james lewis做演讲,讨论了微服务一些原则…...
eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...
基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...
