kdb代码分析(六)

我们带着这个参数回到kdb()里面去看,我们会发现,cpu都会跳到kdba_main_loop().这个函数定义于arch/i386/kdb/kdbasupport.c

577 /*

578 * kdba_main_loop

579 *

580 * Do any architecture specific set up before entering the main kdb loop.

581 * The primary function of this routine is to make all processes look the

582 * same to kdb, kdb must be able to list a process without worrying if the

583 * process is running or blocked, so make all process look as though they

584 * are blocked.

585 *

586 * Inputs:

587 * reason The reason KDB was invoked

588 * error The hardware-defined error code

589 * error2 kdb's current reason code. Initially error but can change

590 * acording to kdb state.

591 * db_result Result from break or debug point.

592 * regs The exception frame at time of fault/breakpoint. If reason

593 * is SILENT or CPU_UP then regs is NULL, otherwise it should

594 * always be valid.

595 * Returns:

596 * 0 KDB was invoked for an event which it wasn't responsible

597 * 1 KDB handled the event for which it was invoked.

598 * Outputs:

599 * Sets eip and esp in current->thread.

600 * Locking:

601 * None.

602 * Remarks:

603 * none.

604 */

605

606 int

607 kdba_main_loop(kdb_reason_t reason, kdb_reason_t reason2, int error,

608 kdb_dbtrap_t db_result, struct pt_regs *regs)

609 {

610 int ret;

611 kdb_save_running(regs);

612 ret = kdb_main_loop(reason, reason2, error, db_result, regs);

613 kdb_unsave_running(regs);

614 return ret;

615 }

这个函数的核心部分自然是kdb_main_loop(),不过在它之前在它之后的这两个函数也有理由引起我们的注意.定义于kdb/kdbsupport.c:

782 /*

783 * kdb_save_running

784 *

785 * Save the state of a running process. This is invoked on the current

786 * process on each cpu (assuming the cpu is responding).

787 * Inputs:

788 * regs struct pt_regs for the process

789 * Outputs:

790 * Updates kdb_running_process[] for this cpu.

791 * Returns:

792 * none.

793 * Locking:

794 * none.

795 */

796

797 void

798 kdb_save_running(struct pt_regs *regs)

799 {

800 struct kdb_running_process *krp = kdb_running_process + smp_processor_id();

801 krp->p = current;

802 krp->regs = regs;

803 krp->seqno = kdb_seqno;

804 krp->irq_depth = hardirq_count() >> HARDIRQ_SHIFT;

805 kdba_save_running(&(krp->arch), regs);

806 }

807

808 /*

809 * kdb_unsave_running

810 *

811 * Reverse the effect of kdb_save_running.

812 * Inputs:

813 * regs struct pt_regs for the process

814 * Outputs:

815 * Updates kdb_running_process[] for this cpu.

816 * Returns:

817 * none.

818 * Locking:

819 * none.

820 */

821

822 void

823 kdb_unsave_running(struct pt_regs *regs)

824 {

825 struct kdb_running_process *krp = kdb_running_process + smp_processor_id();

826 kdba_unsave_running(&(krp->arch), regs);

827 krp->seqno = 0;

828 }

有这么一个结构体以及相应的数组,结构体定义于include/linux/kdbprivate.h:

428 /* Save data about running processes */

429

430 struct kdb_running_process {

431 struct task_struct *p;

432 struct pt_regs *regs;

433 int seqno; /* kdb sequence number */

434 int irq_depth; /* irq count */

435 struct kdba_running_process arch; /* arch dependent save data */

436 };

这其中struct kdba_running_process则定义于include/asm-i386/kdbprivate.h:

159 /* Arch specific data saved for running processes */

160

161 struct kdba_running_process {

162 long esp; /* CONFIG_4KSTACKS may be on a different stack */

163 };

熟悉x86体系结构的同志们一定不会对esp陌生.传说中的栈指针嘛.

kdb_save_runningkdb_unsave_running内部调用了一对函数,它们都来自include/asm-i386/kdbprivate.h:

165 static inline

166 void kdba_save_running(struct kdba_running_process *k, struct pt_regs *regs)

167 {

168 k->esp = current_stack_pointer;

169 }

170

171 static inline

172 void kdba_unsave_running(struct kdba_running_process *k, struct pt_regs *regs)

173 {

174 }

进一步跟踪你会发现,current_stack_pointer其实就是esp寄存器,不信你来看include/asm-i386/thread_info.h:

87 /* how to get the current stack pointer from C */

88 register unsigned long current_stack_pointer asm("esp") __attribute_used__;

标准的gcc内联汇编,相比kernel中众多的内联汇编语句,这句算是最好理解的了.

那么到这里基本上我们就知道了,kdb_save_runningkdb_unsave_running的作用无非就是在真正进入kdb之前保存之前那个进程的一些基本信息以及在从kdb出来以后及时的恢复之.

最后需要提醒一下的是,kdb_running_process不仅仅是结构体的名字,它还是一个数组的名字,该数组定义于kdb/kdbsupport.c:

780 struct kdb_running_process kdb_running_process[NR_CPUS];

对于smp来说,有几个处理器这个数组就有几个元素,对于up来说,自然就是一个成员.kdb_save_runningkdb_unsave_running中都有用到这个数组名,以它为起始地址去计算与某个CPU相关的那个struct kdb_running_process结构体变量,并让krp指向它.

这时候我们就可以全力关注kdb_main_loop().用下半身想想也知道这个函数必然定义于kdb/kdbmain.c:

1506 /*

1507 * kdb_main_loop

1508 *

1509 * The main kdb loop. After initial setup and assignment of the controlling

1510 * cpu, all cpus are in this loop. One cpu is in control and will issue the kdb

1511 * prompt, the others will spin until 'go' or cpu switch.

1512 *

1513 * To get a consistent view of the kernel stacks for all processes, this routine

1514 * is invoked from the main kdb code via an architecture specific routine.

1515 * kdba_main_loop is responsible for making the kernel stacks consistent for all

1516 * processes, there should be no difference between a blocked process and a

1517 * running process as far as kdb is concerned.

1518 *

1519 * Inputs:

1520 * reason The reason KDB was invoked

1521 * error The hardware-defined error code

1522 * reason2 kdb's current reason code. Initially error but can change

1523 * acording to kdb state.

1524 * db_result Result code from break or debug point.

1525 * regs The exception frame at time of fault/breakpoint. If reason

1526 * is SILENT or CPU_UP then regs is NULL, otherwise it

1527 * should always be valid.

1528 * Returns:

1529 * 0 KDB was invoked for an event which it wasn't responsible

1530 * 1 KDB handled the event for which it was invoked.

1531 * Locking:

1532 * none

1533 * Remarks:

1534 * none

1535 */

1536

1537 int

1538 kdb_main_loop(kdb_reason_t reason, kdb_reason_t reason2, int error,

1539 kdb_dbtrap_t db_result, struct pt_regs *regs)

1540 {

1541 int result = 1;

1542 /* Stay in kdb() until 'go', 'ss[b]' or an error */

1543 while (1) {

1544 /*

1545 * All processors except the one that is in control

1546 * will spin here.

1547 */

1548 KDB_DEBUG_STATE("kdb_main_loop 1", reason);

1549 while (KDB_STATE(HOLD_CPU)) {

1550 /* state KDB is turned off by kdb_cpu to see if the

1551 * other cpus are still live, each cpu in this loop

1552 * turns it back on.

1553 */

1554 if (!KDB_STATE(KDB)) {

1555 KDB_STATE_SET(KDB);

1556 }

1557 }

1558 KDB_STATE_CLEAR(SUPPRESS);

1559 KDB_DEBUG_STATE("kdb_main_loop 2", reason);

1560 if (KDB_STATE(LEAVING))

1561 break; /* Another cpu said 'go' */

1562

1563 if (!kdb_quiet(reason))

1564 kdb_wait_for_cpus();

1565 /* Still using kdb, this processor is in control */

1566 result = kdb_local(reason2, error, regs, db_result);

1567 KDB_DEBUG_STATE("kdb_main_loop 3", result);

1568

1569 if (result == KDB_CMD_CPU) {

1570 /* Cpu switch, hold the current cpu, release the target one. */

1571 reason2 = KDB_REASON_SWITCH;

1572 KDB_STATE_SET(HOLD_CPU);

1573 KDB_STATE_CLEAR_CPU(HOLD_CPU, kdb_new_cpu);

1574 continue;

1575 }

1576

1577 if (result == KDB_CMD_SS) {

1578 KDB_STATE_SET(DOING_SS);

1579 break;

1580 }

1581

1582 if (result == KDB_CMD_SSB) {

1583 KDB_STATE_SET(DOING_SS);

1584 KDB_STATE_SET(DOING_SSB);

1585 break;

1586 }

1587

1588 if (result && result != 1 && result != KDB_CMD_GO)

1589 kdb_printf("/nUnexpected kdb_local return code %d/n", result);

1590

1591 KDB_DEBUG_STATE("kdb_main_loop 4", reason);

1592 break;

1593 }

1594 if (KDB_STATE(DOING_SS))

1595 KDB_STATE_CLEAR(SSBPT);

1596 return result;

1597 }

记住,此时此刻,所有的处理器都在这个函数中,只不过其中一个的reason是我们最早传递的那个KDB_REASON_KEYBOARD,而其余的几个cpureasonIPI引起的KDB_REASON_SWITCH,前者只有一个,但是地位相当于正室,后者可以有多个,但是地位相当于小妾.(注释中说,第一个那个叫做in control,而其它的就是不停的spin)

扫一下这个函数发现主要就是一个while(1)死循环.当然,其中有多个break可以跳出循环.不过有意思的是这个死循环内部还有另一个死循环,1549,while(KDB_STATE(HOLD_CPU)),这个就得回忆一下如风的往事了,回过去看kdb(),我们发现,在调用smp_kdb_stop()之前有一俄for循环,把每一个活着的cpu都给设置了两个flag,HOLD_CPUWAIT_IPI.(当然,in control的这个cpu没有设置)直到后来结束了kdba_main_loop()之后,才把这两个flag给人Clear.所以15491557这段while循环对于那些cpu来说,就相当于太上老君把孙猴子困在了炼丹炉中,非得等到一定时间以后才能放出来.这就是注释里说的spin.因此,在下面的代码其它的cpu暂时就不会执行了,只有那个in controlcpu会继续往下走,于是,从此以后,我们就先只关注这一个cpu,而其它的cpu,暂时可以忽略,你愿意想起她就想起她,像想起春天的一个梦,你愿意忘记她就忘记她,像忘记天边的一颗星.

1564,kdb_wait_for_cpus().这个函数就是等待大家都进入kdb.它这个函数的技巧就是判断大家的seqno是不是和kdb_seqno这个全局变量相等,因为实际上如果大家都执行了kdb()函数,那么我们前面说过,kdb_save_running()中就会把各cpu对应的那个seqno赋值为kdb_seqno.于是就应该有1477行的online等于kdb_data从而跳出for循环.反之如果某个cpu或者某几个cpu还没有执行过kdb()函数,那么它们的seqno就不会和全局的这个seqno相等,或者直接说就是初始值0.于是kdb_data就会和online不相等,从而会执行1479行开始的代码,并且开始下一轮的for循环,当然也没什么别的噱头,无非就是做些延时而已.最后只要大家都进入了kdb,这个函数就可以结束了.

Device Info HW是适用于Android设备的硬件和软件信息应用程序。 它正在尝试检测智能手机的组件,以提供有关设备硬件的完整信息。 现在支持检测LCD,触摸屏,相机,传感器,内存,闪存,音频,NFC,充电器,W-FI和电池;如果可能的话,则适用于您的设备。 我认为应用程序对于构建内核或android的用户和开发人员而言非常有趣和有用。 应用程序具有快速导航,新颖的设计,还支持深色主题。 您可以按选项卡切换或使用导航面板。许多项目都是可单击的,您可以转到另一个选项卡或菜单。 设备信息硬件组件 LCD –型号,有时甚至是厂商。对于某些平台,检测需要root用户。 您也可以在LCD测试中检查颜色。 触摸屏–型号,您可以检查多点触摸测试中支持多少手指。 相机–某些平台的型号,供应商,分辨率也可以自动对焦。 如果无法检测到,有时会提供支持的摄像机列表。 硬件信息(按相机型号)和软件(按API)。 对于默认使用5.1+的camera2 api,如果您授予了摄像头许可,则将使用旧api。 设备中有关SoC的详细信息。 CPU:型号,核心,群集,系列,abi,调速器,频率。 GPU:型号,厂商,opengl,频率,扩展列表。 单击时钟速度以打开CPU监视器。 系统:有关固件版本的完整信息。 内存:输入lpddr和工作频率。 闪存:芯片和供应商emmc或ufs(scsi)。 您可以转到内存选项卡,查看内存和存储的使用情况。 电池:基本信息,某些设备还提供其他信息: –放电速度是电流消耗。 –充电速度是充电电流减去电流消耗。 –来自内核的配置文件。仅供参考,仅适用于出厂电池。 –模型。 热量:由温度传感器测得的温度。 传感器:基本传感器的可用性和测试。与我的应用程序“传感器测试”互动。 驱动程序:您可以找到设备中使用的其他芯片。 分区:分区列表及其大小。 PMIC:应用于组件的功率调节器电压的列表。 输入设备:输入设备列表。 应用程序:您可以快速找到应用程序并查看有关它的信息,还提供了系统应用程序的列表。 设备信息硬件附加选项: –显示芯片的i2c地址。 –打开mtk和xiaomi的工程菜单。 –高通,mtk,HiSilicon的CPU代号列表。 –显示具有root访问权限的内核命令行。 设备数据库 您可以找到其他设备的信息,比较并检查类似的驱动程序。它可以在以下网页上找到:http://deviceinfohw.ru 也可以上传设备信息。请参阅信息中心。 设备信息硬件专业版 主题 同时支持明暗主题,选择自己喜欢的主题。 在免费版本中,测试仅需2周即可变暗。 报告 您可以创建包含有关设备信息的报告。 它将保存在html文件中。 您可以打开它或通过共享按钮发送到电子邮件。 请参见示例: http : //www.deviceinfohw.ru/data/report_example.html i2c清单 按总线分组的i2c设备列表。 当智能手机具有许多i2c设备时,此功能很有用。 一些免费标签已被删除。 App Defender可保护您的副本。 这也支持开发以改善应用程序。 支持的平台: 完整:高通,联发科,Exynos,Rockchip,HiSilicon 基本:英特尔,展讯等 低端:某些具有android 7.0+ 注意: –并非所有设备都能读取驱动程序信息,这取决于供应商,供应商。如果需要帮助,请上传设备信息。 –在某些版本为7.0+的设备上,已禁用sysfs读取,并且某些信息不可用。尝试使用root。 如果您想为自己的语言翻译应用程序,或者有有趣的想法或发现错误,请给我写电子邮件或论坛。 要求: – Android 4.0.3及更高版本 权限: –需要INTERNET才能上传设备信息。仅用于手动上传。 –要获取旧相机API的相机软件特征,必须使用CAMERA。 –有关Wi-Fi连接的信息,需要ACCESS_WIFI_STATE。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值