当前位置: 首页 > news >正文

内核调试之Panic-Oops日志分析

这部分我们接着之前的思考,看看内核异常日志的分析。

1 Panic 调试

2 Oops调试

内核出现Panic或Oops错误,如何分析定位问题原因?

首先,保留现场,如下所示为一次非法虚拟地址访问错误。

  EXT4-fs (sdc3): recovery completeEXT4-fs (sdc3): mounted filesystem with ordered data mode. Opts: (null)Unable to handle kernel NULL pointer dereference at virtual address 00000004pgd = cd3cc000[00000004] *pgd=4d3bf831, *pte=00000000, *ppte=00000000Internal error: Oops: 17 [#1] SMP ARMModules linked in: hi_rtc(O) hi_ir(O) hi3536_adec(PO) hi3536_aenc(PO) hi3536_ao(PO) hi3536_ai(PO) hi3536_aio(PO) acodec(PO) gpioi2c(O) hi3536_ive(PO) hi3536_vda(PO) hi3536_jpege(PO) hi3536_h264e(PO) hi3536_chnl(PO) hi3536_venc(PO) hi3536_rc(PO) hi3536_hdmi(O) hifb(PO) hi3536_vou(PO) hi3536_vpss(PO) hi3536_viu(PO) hi3536_vgs(PO) hi3536_region(PO) hi3536_tde(PO) hi3536_jpegd(O) hi3536_vfmw(PO) hi3536_vdec(PO) hi3536_sys(PO) hi3536_base(PO) hiuser(O) hi_media(O) mmz(O) stmmacCPU: 2 PID: 1786 Comm: vecsupgradehisi Tainted: P           O 3.10.0_hi3536 #39task: cfb2bc00 ti: ce164000 task.ti: ce164000PC is at rb_insert_color+0x1c/0x17cLR is at SyS_epoll_ctl+0x584/0x860pc : [<c027e574>]    lr : [<c00f9e2c>]    psr: 60000013sp : ce165f1c  ip : 00000000  fp : 00000000r10: 00000001  r9 : cd3b2304  r8 : cd3b2300r7 : c075a1a8  r6 : cd080980  r5 : cf35a6c0  r4 : cd306000r3 : 00000000  r2 : cd080000  r1 : cd3b233c  r0 : cd080980Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment userControl: 10c5387d  Table: 4d3cc06a  DAC: 00000015PC: 0xc027e4f4:e4f4  e8bd41f0 e12fff13 e3833001 e5843000 e8bd81f0 e5963008 e1a00005 e1a01006e514  e3530000 e5853004 13852001 e5865008 e5846008 15832000 e12fff37 e1a03005e534  e1a05006 e5952004 e3851001 e3520000 e5842008 e5854004 e5831000 1affffd6e554  eaffffd9 e5902000 e3520000 0a000054 e5923000 e3130001 112fff1e e92d4030e574  e593c004 e383e001 e1a05003 e152000c 0a000019 e35c0000 0a000002 e59c4000e594  e3140001 0a00001b e592c004 e15c0000 11a0e002 0a00002c e35c0000 e583c008e5b4  e5823004 0a000001 e3830001 e58c0000 e5930000 e3d0c003 e5820000 e583e000e5d4  05812000 08bd8030 e59c1008 e1530001 058c2008 158c2004 e8bd8030 e593c008LR: 0xc00f9dac:9dac  e288703c e3a02000 e58d7020 e1a03007 ea000005 e596101c e59b201c e06220019dcc  e3520000 da000009 e1a0200b e593b000 e35b0000 0a000007 e5961018 e28b30049dec  e59b2018 e1510002 8afffff6 2afffff0 e28b3008 eafffff3 e30a71a8 e34c70759e0c  e5862000 e1a00006 e586b004 e586b008 e59d1020 e5836000 e58d7018 eb0611ca9e2c  e597c000 e157000c e24cc08c 0a000069 e1a0e00d e3ceed7f e3cee03f e3057dd89e4c  e58d502c e34c7079 e58d4030 e1a0500e e58d6014 e1a0400c e59d6018 ea0000039e6c  e594c08c e156000c e24c408c 0a000056 e595300c e3050dd8 e3091060 e34c00799e8c  e34c100f e1a02004 e58d3000 e1a03004 e587b024 e587b028 e587b02c e587b030SP: 0xce165e9c:5e9c  00000000 00000040 000000d0 c00f9cb4 c09bfef0 00000000 00100100 c027e5745ebc  60000013 ffffffff ce165f04 cd3b2300 c0012b58 cd080980 cd3b233c cd0800005edc  00000000 cd306000 cf35a6c0 cd080980 c075a1a8 cd3b2300 cd3b2304 000000015efc  00000000 00000000 ce165f1c c00f9e2c c027e574 60000013 ffffffff c0446b145f1c  cd306000 cf35a6c0 c00f9e2c 00000000 00000000 00000000 cd08098c cd0809b05f3c  cd306000 c075a1a8 c07500b4 cd3b233c 00000104 cd306018 c00bef44 000000005f5c  0000001c 00000000 c00f8d04 0000001c cd080980 0000001c b3197858 000000105f7c  00000001 00000000 b1e00f08 00000004 b2ffc5e0 000000fb c0013128 ce164000R0: 0xcd080900:0900  00000000 00000000 00000000 00000000 00000000 00000000 00000000 000000000920  00000000 00000000 00000000 00000000 ffffffff ffffffff ffffffff ffffffff0940  ffffffff ffffffff c0756cf0 c0756d20 c0757510 c904b240 c0048858 002000340960  00280006 001d0020 00000000 00000000 00000000 00000000 00000000 000000000980  cd080000 00000000 00000000 cd3b2334 cd3b240c ffffffff cd306000 0000001009a0  00000001 cd23d000 cd23d000 cd3b2300 cd306084 cd306084 00000000 ffffffff09c0  0000001c b3197858 00000010 00000001 c0757510 cecca0c0 c0048858 0020003409e0  00280006 001d0020 00000000 00000000 00000000 00000000 00000000 00000000R1: 0xcd3b22bc:22bc  00000000 00000001 00000001 c0960640 00000000 00000000 cf28f800 0000000022dc  00000000 00000000 00000000 00000000 00000000 00000000 00000000 0000000022fc  00000000 36c236c2 00000000 00000000 cd3b230c cd3b230c cfb2bc00 00000000231c  00000000 cd3b2320 cd3b2320 00000000 cd3b232c cd3b232c cd3b240c cd08098c233c  cd080000 ffffffff 00000000 c0756cf0 cf35a6c0 00000000 00000000 00000000235c  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000237c  00000000 cd3b2400 00000000 00000001 00050005 00000000 00000000 00000000239c  00000000 00000000 00000000 00000000 00000380 00000000 00000000 cd3c1f00R2: 0xcd07ff80:ff80  38343730 205d3032 203c3c3c 696d6448 74636f49 756f206c 2e2e2e74 3c23230affa0  31303030 33303030 23233e33 3030305b 34373030 5d303238 3e3e3e20 6d644820ffc0  636f4969 69206c74 2e2e2e6e 3c23230a 31303030 33303031 30305b23 37303030ffe0  33343834 3c3c205d 6448203c 6f49696d 206c7463 2e74756f 230a2e2e 30303c230000  00000000 cd3b2400 cd080980 cd08000c cd08000c ffffffff cd306180 000000110020  00000001 cd23d028 cd23d028 cd3b2300 cd306204 cd306204 00000000 ffffffff0040  0000001c 00000073 00000011 00000000 c0757510 cf32f780 c0048858 002000340060  00280006 001d0020 00000000 00000000 00000000 00000000 00000000 00000000R4: 0xcd305f80:5f80  00000000 00000000 00000000 00000000 00000000 00000000 00000000 000000005fa0  00000000 00000000 00000000 00000000 00000000 00000000 00000000 000000005fc0  00000000 00000000 00000000 00000000 00000000 00000000 00000000 000000005fe0  00000000 00000000 00000000 00000000 00000000 00000000 00000000 000000006000  cd306000 cd306000 cf823850 cf429aa0 cf4e64a0 c05a5200 00040004 000000006020  00000002 00000802 00000003 00000000 00000000 00000000 00000000 000000006040  00000000 00000000 00000000 00000000 cd3b2200 00000000 00000000 000000006060  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000R5: 0xcf35a640:a640  00000000 00000000 00000000 00000000 cf24a980 00000000 00000000 00000000a660  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000a680  00000000 cf35a684 cf35a684 cf35a68c cf35a68c 00000000 00000000 00000000a6a0  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000a6c0  cf35a6c0 cf35a6c0 cfa58910 cb8b1220 cf4362c0 c0556b74 00000000 00000000a6e0  00000002 00000002 00000003 00000000 00000000 00000000 00000000 00000000a700  00000000 00000000 00000000 00000000 cd3b2200 00000000 00000000 00000000a720  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000R6: 0xcd080900:0900  00000000 00000000 00000000 00000000 00000000 00000000 00000000 000000000920  00000000 00000000 00000000 00000000 ffffffff ffffffff ffffffff ffffffff0940  ffffffff ffffffff c0756cf0 c0756d20 c0757510 c904b240 c0048858 002000340960  00280006 001d0020 00000000 00000000 00000000 00000000 00000000 000000000980  cd080000 00000000 00000000 cd3b2334 cd3b240c ffffffff cd306000 0000001009a0  00000001 cd23d000 cd23d000 cd3b2300 cd306084 cd306084 00000000 ffffffff09c0  0000001c b3197858 00000010 00000001 c0757510 cecca0c0 c0048858 0020003409e0  00280006 001d0020 00000000 00000000 00000000 00000000 00000000 00000000R7: 0xc075a128:a128  00000000 c002e900 00000000 c0795dd4 00000000 c065aa7c c07500b0 00000004a148  000001a4 00000000 c002e900 00000000 c0795dd4 00000000 c065aa90 c07500a8a168  00000004 000001a4 00000000 c002e900 00000000 c0795dd4 00000000 00000000a188  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000a1a8  cd30608c cd30608c c075a1b0 c075a1b0 00000000 00000000 c075a1c0 c075a1c0a1c8  cfb2bc00 00000000 c065aa7c c07500b8 00000004 000001a4 00000000 c002e2c4a1e8  00000000 c0795e10 c075a218 00000000 00000000 00000000 00000000 00000000a208  00000000 00000000 00000000 00000000 7fffffff c0664070 00000000 c00fa6c4R8: 0xcd3b2280:2280  00000001 00000000 cd3b2288 cd3b2288 00000000 00000000 000b000b cd3c3bdc22a0  cd3c3bdc 00000000 00000003 00000010 00000001 00000001 00000002 0000000022c0  00000001 00000001 c0960640 00000000 00000000 cf28f800 00000000 0000000022e0  00000000 00000000 00000000 00000000 00000000 00000000 00000000 000000002300  36c236c2 00000000 00000000 cd3b230c cd3b230c cfb2bc00 00000000 000000002320  cd3b2320 cd3b2320 00000000 cd3b232c cd3b232c cd3b240c cd08098c cd0800002340  ffffffff 00000000 c0756cf0 cf35a6c0 00000000 00000000 00000000 000000002360  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000R9: 0xcd3b2284:2284  00000000 cd3b2288 cd3b2288 00000000 00000000 000b000b cd3c3bdc cd3c3bdc22a4  00000000 00000003 00000010 00000001 00000001 00000002 00000000 0000000122c4  00000001 c0960640 00000000 00000000 cf28f800 00000000 00000000 0000000022e4  00000000 00000000 00000000 00000000 00000000 00000000 00000000 36c236c22304  00000000 00000000 cd3b230c cd3b230c cfb2bc00 00000000 00000000 cd3b23202324  cd3b2320 00000000 cd3b232c cd3b232c cd3b240c cd08098c cd080000 ffffffff2344  00000000 c0756cf0 cf35a6c0 00000000 00000000 00000000 00000000 000000002364  00000000 00000000 00000000 00000000 00000000 00000000 00000000 cd3b2400Process vecsupgradehisi (pid: 1786, stack limit = 0xce164238)Stack: (0xce165f1c to 0xce166000)5f00:                                                                cd3060005f20: cf35a6c0 c00f9e2c 00000000 00000000 00000000 cd08098c cd0809b0 cd3060005f40: c075a1a8 c07500b4 cd3b233c 00000104 cd306018 c00bef44 00000000 0000001c5f60: 00000000 c00f8d04 0000001c cd080980 0000001c b3197858 00000010 000000015f80: 00000000 b1e00f08 00000004 b2ffc5e0 000000fb c0013128 ce164000 000000005fa0: 01fc727c c0012f80 b1e00f08 00000004 0000000e 00000001 00000010 b2ffc5e05fc0: b1e00f08 00000004 b2ffc5e0 000000fb 00000001 00000001 01fc7668 01fc727c5fe0: b3627ddc b2ffc4fc b334f0b0 b608d3bc 60000010 0000000e 00000000 00000000[<c027e574>] (rb_insert_color+0x1c/0x17c) from [<c00f9e2c>] (SyS_epoll_ctl+0x584/0x860)[<c00f9e2c>] (SyS_epoll_ctl+0x584/0x860) from [<c0012f80>] (ret_fast_syscall+0x0/0x30)Code: e5923000 e3130001 112fff1e e92d4030 (e593c004)---[ end trace a35b773550a06f61 ]---

对于最终分析问题原因来讲,以上信息的每一行都很重要。

从上述信息中,我们可以获得出现问题的主要原因(比如,这里的地址错误),出现问题时的现场信息,包括:

1 现场PC指针,LR指针(函数返回时的地址,上一级调用点的下一条指令地址),寄存器地址,堆栈指针等

2 问题出现时当前的进程或者内核线程,关键的调用堆栈

3 除此,内核还将上述寄存器内容所对应内存地址附近的内存信息dump了出来。对于PC来讲,则是机器指令,如最后的Code行

基于上述信息,我们需要分析问题产生的原因,代码中的BUG。

为了便于调试,可以按下述步骤进行操作

首先,编译带debug版本的kernel,在menuconfig中,kernel hacking中,选中with debug info选项

其次,反汇编当前编译的kernel源码,使用交叉编译工具的objdump命令,输入文件为未压缩的内核二进制文件vmlinux

第一步中便于我们定位代码行,第二步便于我们查看实际的汇编指令,以便对应到上述日志信息

完成上述两步后,首先直接调用交叉编译工具链的gdb程序,调试 kernel的 vmlinux文件

输入l *func+0Xab 即可显示问题所在行。对于本奔溃,输入 l *rb_insert_color+0x1c,gdb输出

  0xc027e574 is in rb_insert_color (lib/rbtree.c:94).89                      } else if (rb_is_black(parent))90                              break;9192                      gparent = rb_red_parent(parent);9394                      tmp = gparent->rb_right;95                      if (parent != tmp) {    /* parent == gparent->rb_left */96                              if (tmp && rb_is_red(tmp)) {97                                      /*98                                       * Case 1 - color flips

可见地址0xc027e574能够对应上,且显示了出问题的代码行,为tmp = gparent->rb_right;

其实,有了这个信息,结合日志虚拟地址错误,我们可以猜到gparent是一个空地址。4正好是成员变量的偏移。

一般,找到出问题的代码行之后,可以简单扫扫代码,是否有明显的问题或者问题的原因可能出在什么地方。但是,一般而言,这一步也不会有什么收获。如果是很明显的错误,应该不会这么容易留下来。不过,我们可以先走一个捷径,比如查看Linux内核的修改记录,看看是否有针对当前文件或函数的补丁记录。方法是打开下面的网址,

  https://git.kernel.org/ 在其中找source tree,进一步找针对当前使用的版本

  kernel/git/torvalds/linux.git - Linux kernel source tree

找到对应目录,进入查看修改日志,以确认是否后续更新版本有对当前版本所定位到问题点的代码的修改或补丁

这一步不一定有明显的收获,但是可以用于快速检查,如果正好有,就避免了时间浪费。

如果没有明显的收获,我们可以下载更新版本的完整源码,进行简单对比,看看有什么更新。如果对比后,还是没有收获,则可能需要进一步阅读源码,用以获取更加准确和详细的信息。

实际源码分析时,我们需要注意到,出问题的点只是最后暴露问题的点,问题的引入很可能在之前的调用路径上,所以,可能不仅需要分析当前定位到的代码附近,还需要分析调用者及调用者的调用者

这里,更详细的进一步调试,可以结合反汇编内核得到的汇编指令进行。还是对于上一个例子

  arm-hisiv400-linux-objdump -d vmlinux_nodebug > vmlinux_nodebug_assembler

用上面命令生成汇编代码,用二进制编辑工具打开

也可以只反汇编出问题文件的目标文件,即.o格式的文件,进行汇编代码查看分析

输入出问题的PC地址0xc027e574,可以查看问题点的汇编代码

  c027e558 <rb_insert_color>:c027e558:	e5902000 	ldr	r2, [r0]c027e55c:	e3520000 	cmp	r2, #0c027e560:	0a000054 	beq	c027e6b8 <rb_insert_color+0x160>c027e564:	e5923000 	ldr	r3, [r2]c027e568:	e3130001 	tst	r3, #1c027e56c:	112fff1e 	bxne	lrc027e570:	e92d4030 	push	{r4, r5, lr}c027e574:	e593c004 	ldr	ip, [r3, #4]

可以看到,r3加上4给了IP寄存器,这里r3的内容是多少,可以对应问题现场日志

  pc : [<c027e574>]    lr : [<c00f9e2c>]    psr: 60000013sp : ce165f1c  ip : 00000000  fp : 00000000r10: 00000001  r9 : cd3b2304  r8 : cd3b2300r7 : c075a1a8  r6 : cd080980  r5 : cf35a6c0  r4 : cd306000r3 : 00000000  r2 : cd080000  r1 : cd3b233c  r0 : cd080980

看到r3是0,加4作为虚拟地址,显然是错误的。

其他寄存器,最近的寄存器,及寄存器值作为地址的内存空间,都可以从第一现场获取到,也包括SP堆栈内容。结合寄存器和堆栈及内存,大概可以分析代码出问题的原因。只不过这部分需要对照代码、汇编以及内存数据,仔细分析了。可能需要画出一些数据结构,及相关的地址来仔细分析。

对这里例子,从代码来看,eventpoll结构体对应着一个file描述符,挂载着rbtree的根。每次add ctrl时,添加新的节点。如果节点的父节点为空,说明是根节点,会打上黑树标识,之后会不断添加子节点。

但是从汇编和现场日志来看,当前要添加的节点地址为cd080980,其父节点地址为cd080000,但是父节点的第一个域也就是再上一级节点,为00000000,这与黑树节点类型不符。进一步从内存地址来看,该节点的右孩子,也就是cd080004地址为cb3b2400,左孩子也就是cd080008地址为cd080980,符合当前要添加节点的地址。这样来看,从代码来看,正常应该是不会出现0000000的根节点,至少也是00000001。那问题会出在哪里,内存被修改?节点添加过程意外退出?

另外,需要关注arm调用时,堆栈和参数传递问题。

如此分析,epoll的红黑树应该是出了问题,父节点的父节点为空,代码中没有做判断,是因为基于红黑树的规则不需要进行判断?比如红节点的父节点不是红节点?

最后补充说明内核受污染的信息,来自网络:

  1: 'G': 所有的模块都是GPL的License。如果有模块缺少MODULE_LICENSE()或者声明是Proprietary的,则为'P'。

  2: 'F': 如果有模块是使用 insmod -f 强制载入的。否则为空。

  3: 'S': 如果Oops发生在SMP的CPU上,但这个型号的CPU还没有被认为是SMP安全的。

  4: 'R': 如果有模块是使用 rmmod -f 强制卸载的。否则为空。

  5: 'M': 有CPU报告了Machine Check Exception,否则为空。

  6: 'B': 如果有page-release函数发现一个错误的page或未知的page标志。

  7: 'U': 来自用户空间的程序设置的这个标志位。

  8: 'D': 内核刚刚死掉,比如Oops或者是bug。

  9: 'A': ACPI表被覆盖。

  10: 'W': 之前kernel已经产生过警告。

3 =====RCU-STALL调试=====

补充一下,内核打印中,版本信息中的#xx后面的数字是版本的编译次数。该次数由scripts目录下的脚本生成,每次新生成内核时,该计数增加1,并且会生成一个头文件,包含启动 banner需要的信息。

言归正传。内核运行过程中会出现rcu-stall现象

该现象的典型日志(0702的日志较为有价值,其他的日志,stall所发生的核信息不全)

INFO: rcu_sched detected stalls on CPUs/tasks: { 0 1} (detected by 3, t=4002984 jiffies, g=59256, c=59255, q=494001){ 1}  (t=4003098 jiffies g=59256 c=59255 q=494001)

与rcu有关的一些背景知识,关于tree rcu等,参考博主文档:

https://blog.csdn.net/wwwyue1985/article/details/127347496

基于上述背景,分析该现象的产生原因

要定位具体的问题点,需要继续进一步研究 rcu的调试方法和手段

RCU的调试方法

阅读内核文档中的相关说明,通过分析现象,对应日志,对问题进行定位。另外,也可以尝试人为修改代码引入问题,从而辅助对问题的判断。

修改内核,主动触发rcu,就是人为制造rcu-stall现象

要触发内核错误,最直接的方式就是修改内核代码。应用层要完成这一工作,较为空难,否则,这将是内核的一个漏洞或者BUG被利用了。之前想到可以通过内存的操作,影响到内核,比如通过mmap,进行物理虚拟内存映射进行操作,但是细想起来,映射的还是应用的地址空间,并不能操作到内核地址空间,所以应该是行不通的。

除了应用层,最自然的修改内核的方式就是改动核心代码或者驱动。显然,驱动更直接,且容易切入,影响点较为具体,扩散面也较为容易控制,整体又方便操作实施。这里,为了方便调试,我们采用动态加载的方式进行调试。

RCU-STALL既然是CPU有卡住逻辑,导致宽限期内没有发生调度,即产生平静状态切换(参考内核文档 stallwarn.txt),那么模拟一个死循环,卡住CPU,应该就可以出发STALL了

显然,模拟CPU看著,最简单的就是在中断中或者原子上下文中进行delay,让CPU忙等,类似死锁状态。实际中,采用定时器方案,注册一个字符设备,每当打开设备时,定时器开始工作,这里在定时器中循环调用mdelay,产生长时间忙等状态

另外,为了更详细的展示问题发生时的信息,内核中配置了诸多RCU调试相关的配置。具体参见stallwarn文档。实际中感觉没有多出多少信息。

重新便于内核,刷写,运行。驱动加载并运行后,现象比较容易出现:

  entry test cdev init test cdev have added to system!cdev open file pointer addr is cd2da6c0 entry cdevdev open pdev=  (null)  cdev=  (null) cdev timer will entry after 1s  current jiffies = -15420 cdev timer will entry after 1s  current jiffies2 = -15419 entry cdevdev write 26953552 cdev write file pointer addr is cd2da6c0  pos=0 Driver got data(write by app) 1 Driver got data(write by app) 2 Driver got data(write by app) 3 Driver got data(write by app) 4 Driver got data(write by app) entry cdevdev release cdev release file pointer addr is cd2da6c0 cur atomic count is -1 cdev timer will entry after 1s  current jiffies3 = -15319 timer param is 10004 timer mdelay... 999 timer mdelay... 998 timer mdelay... 997 timer mdelay... 996 timer mdelay... 941 timer mdelay... 940 timer mdelay... 939 INFO: rcu_sched self-detected stall on CPU { 1}  (t=6001 jiffies g=382 c=381 q=106563)Backtrace for cpu 1 (current):INFO: rcu_sched detected stalls on CPUs/tasks: { 1} (detected by 3, t=6002 jiffies, g=382, c=381, q=106563)CPU: 1 PID: 0 Comm: swapper/1 Tainted: P           O 3.10.0_hi3536 #43[<c0019d30>] (unwind_backtrace+0x0/0xf4) from [<c0016de4>] (show_stack+0x10/0x14)[<c0016de4>] (show_stack+0x10/0x14) from [<c0018460>] (smp_send_all_cpu_backtrace+0x70/0xcc)[<c0018460>] (smp_send_all_cpu_backtrace+0x70/0xcc) from [<c007e61c>] (rcu_check_callbacks+0x3a4/0x654)[<c007e61c>] (rcu_check_callbacks+0x3a4/0x654) from [<c00328e0>] (update_process_times+0x40/0x6c)[<c00328e0>] (update_process_times+0x40/0x6c) from [<c00645c8>] (tick_nohz_handler+0xb4/0x11c)[<c00645c8>] (tick_nohz_handler+0xb4/0x11c) from [<c002194c>] (sp804_timer_isr+0x20/0x28)[<c002194c>] (sp804_timer_isr+0x20/0x28) from [<c0076a50>] (handle_irq_event_percpu+0x54/0x17c)[<c0076a50>] (handle_irq_event_percpu+0x54/0x17c) from [<c0076bb8>] (handle_irq_event+0x40/0x60)[<c0076bb8>] (handle_irq_event+0x40/0x60) from [<c0079920>] (handle_fasteoi_irq+0x80/0x158)[<c0079920>] (handle_fasteoi_irq+0x80/0x158) from [<c00762d0>] (generic_handle_irq+0x28/0x40)[<c00762d0>] (generic_handle_irq+0x28/0x40) from [<c0013e9c>] (handle_IRQ+0x40/0x90)[<c0013e9c>] (handle_IRQ+0x40/0x90) from [<c0008514>] (gic_handle_irq+0x34/0x8c)[<c0008514>] (gic_handle_irq+0x34/0x8c) from [<c0012bc0>] (__irq_svc+0x40/0x50)Exception stack(0xcf867e60 to 0xcf867ea8)7e60: 00084885 ffffffff 00003548 c026cfd8 00000342 c07504a4 000003aa cf8660387e80: bf83c03c cf812a14 cf812c14 cf812000 00000001 cf867ea8 bf83c08c c026d0087ea0: 20000113 ffffffff[<c0012bc0>] (__irq_svc+0x40/0x50) from [<c026d008>] (__loop_delay+0x0/0x10)sending IPI to all other CPUs:IPI backtrace for cpu 3CPU: 3 PID: 0 Comm: swapper/3 Tainted: P           O 3.10.0_hi3536 #43task: cf85d400 ti: cf86a000 task.ti: cf86a000PC is at arch_cpu_idle+0x2c/0x30LR is at arch_cpu_idle+0x28/0x30pc : [<c00142a8>]    lr : [<c00142a4>]    psr: 60000013sp : cf86bfe0  ip : 00000000  fp : c0741cf0r10: cf86a000  r9 : cf86a000  r8 : c07775e5r7 : cf86a000  r6 : c0545e6c  r5 : c0741d50  r4 : c07775e5r3 : 00000000  r2 : 00013868  r1 : 00000000  r0 : c09b6930Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment kernelControl: 10c5387d  Table: 4da4c06a  DAC: 00000015PC: 0xc0014228:4228  f10c0040 e3053e6c e34c3054 e5933000 e5930000 e200000f eb09a380 e1a010044248  e59f200c e30400a8 e34c0001 eb0958f2 e7f001f2 c0777888 f1080040 e12fff1e4268  e3a00001 ea004e39 e3a00002 ea004e37 ea148cf5 e92d4008 e3073808 e34c30774288  e5933080 e3530000 0a000002 e12fff33 f1080080 e8bd8008 eb0033ce f108008042a8  e8bd8008 ea004e8b e92d4008 eb0010f8 f10c0080 eafffffe e92d4010 eb0010f442c8  e3073808 e34c3077 e5933084 e3530000 08bd8010 e8bd4010 e12fff13 e92d403842e8  e1a04000 eb0010ea e3053988 e34c3074 e1a01004 e30054a4 e593205c e34c50754308  e5d30000 e3a04ffa e12fff32 e30605b0 e5953004 e3400666 e12fff33 e2544001LR: 0xc0014224:4224  f10c0080 f10c0040 e3053e6c e34c3054 e5933000 e5930000 e200000f eb09a3804244  e1a01004 e59f200c e30400a8 e34c0001 eb0958f2 e7f001f2 c0777888 f10800404264  e12fff1e e3a00001 ea004e39 e3a00002 ea004e37 ea148cf5 e92d4008 e30738084284  e34c3077 e5933080 e3530000 0a000002 e12fff33 f1080080 e8bd8008 eb0033ce42a4  f1080080 e8bd8008 ea004e8b e92d4008 eb0010f8 f10c0080 eafffffe e92d401042c4  eb0010f4 e3073808 e34c3077 e5933084 e3530000 08bd8010 e8bd4010 e12fff1342e4  e92d4038 e1a04000 eb0010ea e3053988 e34c3074 e1a01004 e30054a4 e593205c4304  e34c5075 e5d30000 e3a04ffa e12fff32 e30605b0 e5953004 e3400666 e12fff33

因为RCU-STALL检测超时时间设置为了60,所以可以看到,60秒后,stall现象暴露出来

  INFO: rcu_sched self-detected stall on CPU 

跟实际设备上的原因信息一致,当然,具体原因有差异

我们来分析日志,看是否能够从日志中定位出人为制造的问题点

首先,主要看看堆栈信息,从日志打印的堆栈中可以看出,最终是在时钟滴答中断中,调用rcucallback检查,发现超过了宽限期,然后主动dump内核异常信息。并且发送了IPI给其他核心,触发其他核心的寄存器、内存和堆栈信息。不过,对于这里的stall问题,其他核心的信息仅仅参考,当前看来,并不具有太大意义这样,整体一看,整个日志信息似乎表达的都是废话

但是我们需要注意一个细节,问题出现的核心的硬件中断前的日志信息,这是最关键的,结合当前情况,个人的理解。

  [<c0008514>] (gic_handle_irq+0x34/0x8c) from [<c0012bc0>] (__irq_svc+0x40/0x50)Exception stack(0xcf867e60 to 0xcf867ea8)7e60: 00084885 ffffffff 00003548 c026cfd8 00000342 c07504a4 000003aa cf8660387e80: bf83c03c cf812a14 cf812c14 cf812000 00000001 cf867ea8 bf83c08c c026d0087ea0: 20000113 ffffffff[<c0012bc0>] (__irq_svc+0x40/0x50) from [<c026d008>] (__loop_delay+0x0/0x10)

中断irq_svc是在loop_delay的时候调用的,这非常关键

对于这里给出的地址,像c026d008  c0012bc0 我们可以在当前编译内核的目录进行定位,通过交叉编译链的arm----gdb工具,不过前提是内核需要是debug版本。

如果没有编译debug的vmlinux,还是可以分析的,有两种方法

一种是在当前编译内核的目录下通过System.map文件来分析,该文件中保存有内核符号和地址的映射对应关系

一种是根据运行设备的/proc/kallsyms符号表进行定位

鉴于这里,内核已经卡死了,我们选择第一种,可以在不用重启设备的情况下,进行分析

比如,选择这种方法,

  cat System.map | grep c0012bc0

但是考虑到地址可能对于函数开始有偏移,所以大部分时候除非是在函数调用开始,否则几乎不会输出任何东西。所以我们可以查看该地址附近的信息,比如,通过下面这种方法,省略掉后两位地址位,看是否有匹配

  cat System.map | grep c0012b

  c0012b20 t __dabt_svc

  c0012b80 t __irq_svc

  c0012bd0 t __und_fault

  c0012be0 t __und_svc

我们看到这个地址附近的函数,跟上述日志信息里的函数是有一致的。从这里获取开始地址,加上日志中的偏移,结合反汇编,基本可以定位出调用栈所在的代码。当然,前提是内核不要有新的修改编译,否则,上述地址就可能发生变化。

我们再看看调用者的地址

  cat System.map | grep c026d008

  c026d008 T __loop_delay

说明是在loog_delay函数中发生了中断,然后触发了stall的检查条件。所以,问题很可能是在该loop_delay相关的函数中。这里有两点引申含义:

1 是说问题可能是由delay导致。这一点比较容易猜想。当delay在让CPU卡住等待时,如果时间过长,显然肯定会触发rcu-stall的。

2 是说大概就是在delay相关的接口中。为什么是大概呢?当然,这里的前提还是假设是由delay导致了问题。这涉及到内核的编译处理。

我们知道,函数调用涉及入栈出栈的问题,如果只是一个简单的函数,当被频繁调用,那么光是栈处理消耗的CPU就可能远大于函数本身的逻辑处理对CPU的占用。所以,这就导致内联函数的产生。更进一步的,如果一个函数是静态的,且只在当前文件中被调用了一次,那么编译器可能也会将其优化为类似内联函数形式。

说了这么多,其实要表达的核心思想是代码中看到的函数调用不一定在编译后还是原本的函数调用,可能就被嵌入到调用者的汇编里了,在汇编代码中看不出有函数调用痕迹。这样一来,对定位代码,就产生了一些干扰。我们需要结合dump栈中的偏移和汇编代码,结合内核代码,一起定位调用点在原始C代码中的那个位置。

实际调试时,常会发现,汇编中的调用总是少于实际C代码的,就是因为很多成为了调用者内部逻辑,规避了利用栈传递参数的逻辑。

对于ARM架构来讲,大部分介绍是说函数调用通过寄存器结合堆栈进行参数传递的,这一点在跟踪汇编代码时需要注意。

有了上述信息,就可以围绕已有线索,展开问题原因的定位分析。

单纯看delay,虽然与问题的原因很容易对应上,但是范围太广。delay是非常基础的函数,在内核中调用点散步很广,很难直接下手。这时候,就需要对当前CPU的堆栈进行分析。因为堆栈可能会给出这个delay的具体调用者。从而提供更准确的信息。堆栈中记录的调用者,与真正导致问题的代码,可能比较接近。

上面的日志中也给出了异常栈信息。按照从高地址向低地址增长的方式来看,低地址处应该是更接近CPU现场的被调用点,高地址是调用者

考虑到内核地址在3-4GB范围内,即C0000000--F0000000地址空间,所以可以特别关注C开头的地址,很可能是内核地址

  c026d008     c026d008 T __loop_delay

  cf867ea8  非内核地址

  cf812000  cf81开始的这几个也不是内核地址 可能是内核数据空间,也可能是参数地址

  c07504a4 c07504a4 D arm_delay_ops

可见loop_delay是由该函数调用到的

struct arm_delay_ops arm_delay_ops = {.delay		= __loop_delay,.const_udelay	= __loop_const_udelay,.udelay		= __loop_udelay,};

从实际的代码中可以对应上

  c026cfd8    c026cfd8 T __loop_const_udelay

从目前的堆栈分析来看,函数调用似乎就这么多了。另外一些数据,可以猜测验证,也是有帮助的。比如000003aa,十进制就是938,是timedelay的计数值,反推时,我们可以使用该值验证人为的出发点,比如1000-938接近60。但是正向跟踪其实是有点难度的.不过,不管怎样,也是一些重要信息。可能就在这些蛛丝马迹中发现问题点。还比如,一些0或者1的值,可能就跟布尔条件变量有关等等。

其实这里的例子,还有一些特殊性。为了验证问题,采用了动态加载模块的方式

我们对模块进行反汇编看一下arm-hisiv400-linux-objdump -d testdrv.ko

发现其中的地址都是相对地址,偏移是基于00000000的,所以模块的实际地址,可能是在insmod的时候,由内核重新分配的。这样来看,堆栈中的地址在内核编译符号中找不到,可能能够讲得通了。同时,从另外一个角度来看,如果产品中存在这种动态加载的模块,那么当问题产生时,给问题的定位会带来一些额外的复杂度和工作。

在保留堆栈日志信息的前提下,我们重新加载模块,进行进一步的定位分析。

  cat /proc/modules 可以查看到外部模块的地址信息

  testdrv 6256 0 - Live 0xbf83c000 (O)

比如这里的测试模块,可以看到是在0xbf83c000这个地址开始的空间内

此时,再回看堆栈日志信息,可以看到有两个地址可疑

第一个,bf83c08c,此时模块是动态加载,需要在运行的内核中查看,方法同前述

~ # cat /proc/kallsyms | grep bf83c0bf83c000 t $a   [testdrv]bf83c00c t my_tasklet_func      [testdrv]bf83c0b4 t cdevdev_write        [testdrv]bf83c03c t cdevdev_timer        [testdrv]bf83c000 t add_var      [testdrv]

第二个,bf83c03c,跟之前一样

从这两个地址,可以初步定位出问题关键点,timer函数。

接下来,就需要根据上述地址的具体便宜结合汇编定位出C代码,然后检查代码了。因为是人为制造的触发流程,代码简单直接

   int count = 1000;while(count--) {mdelay(1000);printk(KERN_INFO "timer mdelay... %d \n", count);}

到这一步,根据日志定位代码的流程基本就完成了。从上述流程来看,异常栈是非常非常重要的信息。

在这整个过程中,还有几个问题需要明确:

需要明确,每次insmod模块时,CPU会分配相同的地址吗?从上面重新加载模块,定位函数来看,地址似乎是一样的。这是巧合还是固有设计,待验证。

insmod模块时,是加载到用户空间地址还是内核空间地址?从上述日志来看,是在用户空间了?因为是B开头的地址。

虽然如上分析,问题定位在delay中,但也只是一种可能得到了验证。因为根据RCU-STALL的原理来讲,还是有其他可能的,包括

 本cpu的其他地点,这里只是凑巧在中断前的地址中发现了问题,并凑巧在模块中得到了定位。关键还是要找到宽限期后未经历静止状态的CPU核及其上任务。

2 其他CPU的可能性。这一点可以通过绑定CPU核心来验证。比如将驱动模块的定时器绑定到其他CPU核心上,默认时钟滴答是否应该在CPU0上?可以编码来验证这一点。

如果得到验证,那么其他CPU的寄存器和堆栈就非常值得分析了。

答案应该是明确的。因为存在其他CPU检测到当前CPU出现stall问题。

如果问题最终能定位,则可以用该内核放到产品中定位产品测试中出现的stall现象

如果不能,则采用重启等补充手段?

手段1 ,使用延迟队列的 restart,参见前述kernel_restart部分。

如果循环触发rcu-stall,放在工作队列中的restart是否有机会调用,待验证。

经过验证,该restart几乎没有机会执行。

在应用层,部分命令还是可以正常执行,比如top,可以查看进程和线程的情况。

但是,应用层的定时喂狗似乎是存在问题的,超时后,单片机重启了设备,是因为内核卡住定时器不准了还是应用执行被停住了?猜测这里是因为insmod的测试驱动使用了mdelay,卡住了cpu,可能导致该核心上的应用定时器不再准确,从而导致喂狗mcu失败

该机制目前看不太可靠,内核的运行逻辑不是固定的。

手段2,使用panic,当发现rcu-stall后,主动触发panic,可以挂死上层应用,触发单片机看门狗

手段3,启用看门狗,验证panic和rcu-stall是否会影响到内核中断处理,从而触发cpu内部看门狗

首先,对于单纯rcu-stall,感觉不会影响到硬件中断,实际测试,确实不会影响中断,串口输入还可以正常使用。但是reboot命令本身不起作用。

其次,对于panic加看门狗,测试看可以生效,到时间后,cpu被复位

综上,针对rcu-stall要重启设备的话,可以使用panic结合上层应用使用的MCU喂狗机制,可以完成系统的硬复位。内核看门狗作为一种补充手段保留。

其实,panic可以使用一个超时参数,在panic发生后,经过超时时间后重启设备。这需要配置内核,但是这个重启是否管用,待测试。

经过测试,该超时在rcu-stall上下文掉用不能够完成重启,跟前述kernel_restart表现一致。因为之前直接调用重启函数不管用,才使用了工作队列方式,才有了这里所描述的上述方案。

最终的方式就是:出现RCU-STALL--触发panic--触发内核看门狗--如果失败,触发应用看门狗。两重保障。panic timeout可以保留,也可以不保留,应该会屏蔽CPU中断,这里选择保留。

根据stallwarn文档,产生stall的可能原因包括:

1 一个CPU在一个RCU读关键区循环. == 对应RCU的宽限期图示,如果CPU没有出来,宽限期就会超时.

2 一个CPU在中断关闭的情况下循环。这个条件会导致RCU-sched和RCU-bh产生stall == 中断关闭时,如果循环,则存在无法打破循环的问题。

3 一个CPU在抢占关闭的情况下循环。这个条件可以导致RCU-sched stalls,并且如果ksoftirqd在使用,RCU-bh 会stalls。

4 一个CPU在下半部关闭的情况下循环。这个条件会导致RCU-sched和RCU-bh stalls

5 对于非抢占内核,CPU在内核任意地方循环,而没有主动执行调度。===这个条件有个疑问,(2 3 4 条也是),就是中断是否会影响stall的判断?从stall堆栈中还能看到中断来看,中断本身对stall的影响是比较小的

6 其他一些条件,包括RCU本身的bug、硬件bug等。

相关文章:

内核调试之Panic-Oops日志分析

这部分我们接着之前的思考&#xff0c;看看内核异常日志的分析。 1 Panic 调试 2 Oops调试 内核出现Panic或Oops错误&#xff0c;如何分析定位问题原因&#xff1f; 首先&#xff0c;保留现场&#xff0c;如下所示为一次非法虚拟地址访问错误。 EXT4-fs (sdc3): recovery c…...

论文解读 | [AAAI2020] 你所需要的是边界:走向任意形状的文本定位

目录 1、研究背景 2、研究的目的 3、方法论 3.1 Boundary Point Detection Network(BPDN) 3.2 Recognition Network 3.3 Loss Functions 4、实验及结果 论文连接&#xff1a;https://ojs.aaai.org/index.php/AAAI/article/view/6896 1、研究背景 最近&#xff0c;旨在…...

数据挖掘流程简单示例10min

数据挖掘流程简单示例10min 套路&#xff1a; 准备数据实现算法测试算法 任务1&#xff1a;亲和性分析 如果一个顾客买了商品X&#xff0c;那么他们可能愿意买商品Y衡量方法&#xff1a; 支持度support : 所有买X的人数 置信度confidence : 所有买X和Y的人数所有买X的人数…...

KDJB1200六相继电保护测试仪

一、概述 KDJB1200继电保护测试仪是在参照电力部颁发的《微机型继电保护试验装置技术条件(讨论稿)》的基础上&#xff0c;广泛听取用户意见&#xff0c;总结目前国内同类产品优缺点&#xff0c;充分使用现代新的的微电子技术和器件实现的一种新型小型化微机继电保护测试仪。可…...

从WEB到PWA 开发-发布-安装

见意如题&#xff01;本文主要来说说PWA开发&#xff01;作为一个前端程序员&#xff0c;在没有任何Android/IOS的开发情况下&#xff0c;想想我们有多少种方法来开发一个原生移动应用程序&#xff01;我们可以有非原生、混合开发&#xff0c;PWA等等手段。类似uniapp&#xff…...

FPGA纯vhdl实现MIPI CSI2 RX视频解码输出,OV13850采集,提供工程源码和技术支持

目录1、前言2、Xilinx官方主推的MIPI解码方案3、纯Vhdl方案解码MIPI4、vivado工程介绍5、上板调试验证6、福利&#xff1a;工程代码的获取1、前言 FPGA图像采集领域目前协议最复杂、技术难度最高的应该就是MIPI协议了&#xff0c;MIPI解码难度之高&#xff0c;令无数英雄竞折腰…...

《NFL橄榄球》:卡罗来纳黑豹·橄榄1号位

卡罗来纳黑豹&#xff08;英语&#xff1a;Carolina Panthers&#xff09;是一支位于北卡罗来纳州夏洛特的职业美式橄榄球球队。他们是国家美式橄榄球联合会的南区其中一支球队。他们与杰克逊维尔美洲虎在1995年加入NFL&#xff0c;成为扩充球队。 2018年球队市值为23亿美元&am…...

我说我为什么抽不到SSR,原来是这段代码在作祟...

本文是龚国玮所写&#xff0c;熊哥有所新增修改删减&#xff0c;原文见文末。 我说我为什么抽不到SSR&#xff0c;原来是加权随机算法在作祟 阅读本文需要做好心理准备&#xff0c;建议带着深究到底的决心和毅力进行学习&#xff01; 灵魂拷问 为什么有 50% 的几率获得金币&a…...

MySQL MGR 集群新增节点

前言 服务器规划现状&#xff08;CentOS7.x&#xff09; IP地址主机名部署角色192.168.x.101mysql01mysql192.168.x.102mysql02mysql192.168.x.103mysql03mysql192.168.x.104proxysql01proxysql、keepalived192.168.x.105proxysql02proxysql、keepalived 新增服务器IP&#x…...

【单目标优化算法】蜣螂优化算法(Dung beetle optimizer,DBO)(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

【C++】类和对象入门必知

面向过程和面向对象的初步认识类的引入类的定义类的访问限定符封装类的作用域类的实例化类对象模型this指针C语言和C实现Stack的对比面向过程和面向对象的初步认识 C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解…...

day38 动态规划 | 509、斐波那契数 70、爬楼梯 746、使用最小花费爬楼梯

题目 509、斐波那契数 斐波那契数&#xff0c;通常用 F(n) 表示&#xff0c;形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始&#xff0c;后面的每一项数字都是前面两项数字的和。也就是&#xff1a; F(0) 0&#xff0c;F(1) 1 F(n) F(n - 1) F(n - 2)&#xff0c;其…...

2023年备考软考必须知道的6件事

不知不觉&#xff0c;距离2023年上半年软考也只有不到100天的时间了&#xff0c;报名入口也将在3月13日正式开通&#xff0c;你是正在犹豫是否参加考试? 还是已经开始着手准备复习? 关于软考考试你还有哪些疑问? 2023年备考软考必须知道的6件事&#xff0c;建议收藏&#xf…...

GLOG如何控制输出的小数点位数

1 问题 在小白的蹩脚翻译演绎型博文《GLOG从入门到入门》中&#xff0c;有位热心读者提问说&#xff1a;在保存日志时&#xff0c;浮点型变量的小数位数如何设置&#xff1f; 首先感谢这位“嘻嘻哈哈的地球人”赏光阅读了小白这不太通顺的博客文章&#xff0c;并提出了一个很…...

2022年全国职业院校技能大赛(中职组)网络安全竞赛试题A(6)

目录 模块A 基础设施设置与安全加固 一、项目和任务描述&#xff1a; 二、服务器环境说明 三、具体任务&#xff08;每个任务得分以电子答题卡为准&#xff09; A-1任务一&#xff1a;登录安全加固&#xff08;Windows&#xff09; 1.密码策略 a.密码策略必须同时满足大小…...

Safety-Gym环境配置与安

官网&#xff1a; https://github.com/openai/safety-gym https://github.com/openai/safety-starter-agents 一、安装依赖环境配置 建议使用python 3.7及以下环境&#xff0c;因为官方的safety-rl是基于tensorflow1.13.1实现&#xff0c;而tensorflow1.13.1只能支持python…...

3月再不跳槽,就晚了

从时间节点上来看&#xff0c;3月、4月是每年跳槽的黄金季&#xff01; 以 BAT 为代表的互联网大厂&#xff0c;无论是薪资待遇、还是平台和福利&#xff0c;都一直是求职者眼中的香饽饽&#xff0c;“大厂经历” 在国内就业环境中无异于一块金子招牌。在这金三银四的时间里&a…...

HTTP cookie格式与约束

cookie是前端编程当中经常要使用到的概念&#xff0c;我们可以使用cookie利用浏览器来存放用户的状态信息保存用户做了一些什么事情。session是服务器端维护的状态。session又是如何和cookie关联起来。后面介绍cookie和session的使用。Cookie 是什么&#xff1f;RFC6265, HTTP …...

docker基础

docker基础 docker概述 docker的出现&#xff1f;docker解决思想docker历史docker链接docker能干什么&#xff1f;开发-运维 docker安装 镜像(image)容器(container)仓库(repository)底层原理 docker命令 帮助命令镜像命令 docker-images查看所有本地主机上的镜像docker-searc…...

【微信小程序】--JSON 配置文件作用(三)

&#x1f48c; 所属专栏&#xff1a;【微信小程序开发教程】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#…...

EDA-课设

EDA-课程设计-电子闹钟 一、实验目的 1.掌握多层电路在 QuartusII 集成开发环境中的实现&#xff1b; 2.熟练掌握基于 QuartusII 集成开发环境的组合逻辑电路设计流程&#xff1b; 3.掌握基于 QuartusII 集成开发环境的时序逻辑电路设计流程&#xff1b; 4.理解有限状态机设计…...

C/C++每日一练(20230222)

目录 1. 部分复制字符串(★) 2. 按字典顺序排列问题(★★) 3. 地下城游戏(★★★) 附录 动态规划 1. 部分复制字符串 将字符串2小写字母复制到字符串1&#xff1a;编写程序,输入字符串s2,将其中所有小写字母复制到字符串数组strl中。例如&#xff1a;aal1bb22cc33de4AA55…...

Java API 文档搜索引擎

1. 认识搜索引擎:在搜狗搜索的搜索结果页中, 包含了若干条结果, 每一个结果包含了图标, 标题, 描述, 展示URL等搜索引擎的本质:输入一个查询词, 得到若干个搜索结果, 每个搜索结果包含了标题, 描述, 展示URL和点击URL2. 搜索引擎思路:2.1 搜索的核心思路:当前我们有很多的网页(…...

2023美赛C题Wordle二三问分布预测和难度分类预测

文章目录前言题目介绍人数分布预测首先建立字母词典&#xff0c;加上时间特征数据预处理训练和预测函数保存模型函数位置编码模型及其参数设置模型训练以及训练曲线可视化预测人数分布难度分类预测总结前言 2023美赛选了C题&#xff0c;应该很多人会选&#xff0c;一看就好做&…...

gdb的简单练习

题目来自《ctf安全竞赛入门》1.用vim写代码vim gdb.c#include "stdio.h" #include "stdlib.h" void main() {int i 100;int j 101;if (i j){printf("bingooooooooo.");system("/bin/sh");}elseprintf("error............&quo…...

如何使用python AI快速比对两张人脸图像?

本篇文章的代码块的实现主要是为了能够快速的通过python第三方非标准库对比出两张人脸是否一样。 实现过程比较简单&#xff0c;但是第三方python依赖的安装过程较为曲折&#xff0c;下面是通过实践对比总结出来的能够支持的几个版本&#xff0c;避免大家踩坑。 python版本&a…...

(2)C#传智:变量基础(第二天)

一、注释符 不写注释是流氓&#xff0c;名字瞎起是扯蛋。 注释作用&#xff1a;解释与注销 命名&#xff1a; 以字母、_、开头&#xff0c;里面只能有_与特殊符&#xff0c;其它不得出现如%*&^等。 不能与关键字重复。区分大小写&#xff0c;Num…...

02-mysql高级-

文章目录mysql高级1&#xff0c;约束1.1 概念1.2 分类1.3 非空约束1.4 唯一约束1.5 主键约束1.6 默认约束1.7 约束练习1.8 外键约束1.8.1 概述1.8.2 语法1.8.3 练习2&#xff0c;数据库设计2.1 数据库设计简介2.2 表关系(一对多)mysql高级 今日目标 掌握约束的使用 掌握表关系…...

windows 使用everything 查看文件(夹)存储空间占用

起因 总是那个原因,C: D: E:全都红了,下的游戏太多了,然后就这样了,之前也有过不少这种情况.几年前,就在智能手机上见过类似的功能. 大概就是遍历文件系统,统计每个文件的大小,然后父节点记录所有子节点的和,然后可以显示占用百分比之类的. 经过 在windows 上我最开始使用ex…...

2023该好好赚钱了,推荐三个下班就能做的副业

在过去的两年里&#xff0c;越来越多的同事选择辞职创业。许多人通过互联网红利赚到了他们的第一桶金。随着短视频的兴起&#xff0c;越来越多的人吹嘘自己年收入百万&#xff0c;导致很多刚进入职场的年轻人逐渐迷失自我&#xff0c;认为钱特别容易赚。但事实上&#xff0c;80…...