




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、红帽linux故障定位技术详解与实例红帽linux故障定位技术详解与实例是本文要介绍的内容,主要是来了解并学习红帽linux中 故障定位技术的学习,故障定位技术分为在线故障定位和离线故障定位,一起来看详解。1、故障定位(debugging)场景分类为便于描述问题,将linux上各种软件故障定位的情形分成两类:(1) 在线故障故障定位在线故障定位(online-debugging)就是在故障发生时,故障所处的操作系统环境仍然可 以访问,故障处理人员可通过console, ssh等方式登录到操作系统上,在shell上执行各种操 作命令或测试程序的方式对故障坏境进行观察,分析,测试,以定位出故障发生
2、的原因。(2) 离线故障定位离线故障定位(offline-debugging)就是在故障发牛时,故障所处的操作系统环境已经无法 正常访问,但故障发生时系统的全部或部分状态已经被系统本身所固有或事先设定的方式收集起 来,故障处理人员可通过对收集到的故障定位状态信息进行分析,定位出故障发生的原因。2、应用进程故障情形及处理应用进程的故障一般不会影响操作系统运行环境的止常使用(如果应用代码的bug导致了 内核的crash或hang,则属于内核存在漏洞),所以可采用在线故障定位的方法,灵活的进行 分析.应用代码故障的情形有如下几种:(1) 进程异常终止很多用户认为进程异常终止情况无从分析,但实际上进程
3、异常终止情况都是有迹可寻的.所 有的进程异常终止行为,都是通过内核发信号给特定进程或进程组实现的.可分成儿个类型进行 描述:sigkill. sigkill最特殊,因为该信号不可被捕获,同时sigkill不会导致被终止的进 程产生core文件,但如果真正的是由内核中发出的sigkill,则内核一定会在dmesg中记录 下信息.另外在内核中使用sigkill的地方屈指町数,如oom_kill_process()中,所以通过 dmesg记录并且分析内核中使用sigkill的代码,并不难分析原因-sigquit, sigill, sigabrt, sigbus, sigfpe, sigsegvo 这
4、几个信号在保留情 况下会终止进程并会产生core文件,用户根据core中的stack trace信息,能直接定位出导致 终止信号的代码位置。另外,sigquit, s1gabrt -般是由用户代码自己使用的,好的代码一 般会记录日志。sigill, sigbus, sigfpe, sigsegv,都是由内核屮产生的,搜索内核源 码,不难列出内核屮使用这几个信号的地方,如sigill是非法指令,可能是浮点运算产生的代 码被corrupted或文本区域的物理内存corruption; sigbus多由mce故障定位导致:sigsegv 多由应用代码的指针变量被corrupted导致。对于应用的he
5、ap或stack的内存被corrupted,可 用valgrind工具对应用进行profile,通常能直接发现导致corruption的代码sigint, sigpipe, sigalrm, sigterm-这几个信号在保留情况下终止进程但不会产 牛core文件。对这几个信号,建议用户一定要定义一个handler,以记录产生问题的上下文。 比较容易忽略的是sigpipe,很多用户程序在使用selector poll()时只监听read/write描述符, 不监听exception描述符,在对方tcp己经关闭的情况下,仍然向socket中写入,导致sigpipe。对于恶意的代吗产生的进程终止行为
6、,如合作的一些进程屮,a向b发sigkill,而没做 日志记录,或者b直接判断某条件而调用exit(),也没有做日志记录在应用代码量很大的情况下, 通过分析代码故障定位这种情形也许很难.systemtap提供了解决这个问题的一个比较好的方 法,就是写用八层的probes,追踪进程对signal(), exit()等系统调用的使用(2) 进程阻塞,应用无法正常推进这种情况,对于单个被阻寒的进程而言,属于正常状态,但对于包含多个进程的应用整体而 言,属于异常。应用无法推进,说明其中某一个进程推进的因素出现了问题,导致其他依赖于它 的进程也要等待.分析这种情形需要分析清楚进程或事件之间的依赖关系,及
7、数据的处理流。首 先要用gdb -p的back trace功能查出各进程阻塞的执行路径,以确定每个进程所处在的状态机 的位置。通常而言,如果只考虑各个进程的状态,则进程之间可能形成了一种互相依赖的环形关系, 如(p1发请求=>p2处理=>p2发反应=>p1再请求=>p2处理=>p2再发反应),但应用对 workload,般是按一个个的transaction或session的方式进行处理的,每个transaction都 有起点和终点,我们需要用strace, tcpdump等工具以及应用的执行日志进行观察,分析出当 前正被处理的transaction所被阻滞的位置,
8、从而找出全部状态机被阻塞的原因。导致这种状态 机停止运转的原因有多个:如和应用通信的远端出现了问题,后端数据库/目录等出现了问题, 应用的某个进程或线程处于非正常的blocking位置或直接终止,不再正常工作。(3) 用户进程形成死锁用户进程形成死锁,如果没有内存上的故障定位,则完全是应用自身的逻辑问题。死锁的进 程或线程z间由于锁的互相占有形成了环路。这种情况发生时,用gdb -p的back trace的功能 能直接确定死锁的进程全部阻塞在futex()等和锁相关的系统调用上,这些调用futex()的路径可 能是 mutex, semaphore, conditional variable
9、等锁函数。通过分析 call trace 的代码,能 直接确定各进程在执行到该位置时,可能已经持有的全部锁,根据这个修改程序的代码,消除死 锁环路,就可解决问题。注意,内存故障也可导致假的死锁的,如物理内存故障可直接导致锁变量的值为-1,所以使 用该锁的进程都会阻塞.如果是代码的bug导致的内存corruption,可用valgrind i具检查程序 来发现。但如果是物理内存的故障定位导致的corruption,则需耍硬件的支持,对于高端的pc, 如mce功能的机器,当物理内存故障定位时能直接产生异常或报告,但对于低端pc服务器, 除了运行memtest工具进行检测外,没有其他方法。(4)进程
10、长期处于 d (uninterruptible)状态没法退出这种多是由内核中的故障引起的。内核在很多执行路径中会将进程至于'd的状态,以确保 关键的执行路径不被外部的信号中断,导致不必要的内核中数据结构状态的不一致性。但一般而 言,进程处于状态的时间不会太久,因为状态结朿的条件(如timer触发,i0操作完成等) 很快会将进程唤醒.当进程长期处于关键是要找出其阻塞的代码位置,用sysrq的t键功 能可直接打印出系统屮全部睡眠进程的内核执行堆栈,如echo't* >/proc/sysrq-trigger,其中包 括出现d状态的进程的内核态堆栈。找出代码位置后,一般可直接分析
11、出d状态不能退出的 原因,如loread操作因硕件或nfs故障而不能完成。有可能导致d状态的原因比较复杂,如 'd,的退出依赖于某变量的值,而该变量的値因某种原因被永久corrupted掉了。3、内核故障情形及处理(1) 内核 panicpanic是内核最直接的故障定位报告,发生panic时,内核已经认为故障定位已经导致操作 系统不再具备正常运行的条件了。当发牛panic时,linux会将所冇cpu的中断和进程调度功 能都关掉,所以这时系统是没有任何反应的,如果用户启动的是图形界面,则在屏幕上也看不到 任何关于panic的信息。我们通常遇到的,机器没反应,ping不通的情况,绝大部分都
12、是panicc panic发生时, 内核直接在console上打印导致panic的代码位置的调用堆栈,传统的用户用串口连接到机器上 来收集console上的打印信息,但串口这种方式,显然用起来不方便,现在的linux,如rhel5, rhel6,都采用kdump的方法来收集panic时的信息。在配置好kdump的情况下,panic时系 统会用kexec加载并切换到一个新的内核上(放置在预先分配的内存位置),并用磁盘或网络 等将系统的全部或部分内存数据保存起来。用kdump收集到panic的数据后,用户用crash工具就能直接查看导致panic的代码路径。panic 一般是很直观的,panic的
13、堆栈信息能直接反映出导致bug的原因,如mce故障, nmi故障,数据结构分配失败等。但有时panic是因为内核主动发现了关键的数据结构不一致性, 这种不一致性是什么时候,什么代码导致的,并不清楚,可能还需要多次测试用systemtap这 样的工具进行捕捉(2)多处理机环境内核执行路径产生的死锁内核死锁和panic不一样,产牛死锁时,内核并不主动的使自己处于挂起状态。但内核死 锁发生时,两个以上的cpu的执行路径在内核态不能推进了,处于互相阻塞状态,而且是100% 的占用cpu (用的spin-lock),直接或间接的导致全部cpu上的进程无法调度。内核死锁又 分两种情况:涉及到中断上下文的死
14、锁。这种情况的死锁,最少一个cpu上的中断被屏蔽了。系统可 能没法响应ping请求。山于有一个cpu己经没法响应中断,其上的local apic定时中断没法 工作,可以用nmi watchdog的方法来检测出来(检查local apic handler维护的计数器变量), nmi watchdog可以在其处理程序中调用panic (),用户就可以用kdump收集内存信息,从 而分析各死锁cpu上的调用堆栈,查处导致死锁的逻辑原因。不涉及中断上下文的死锁。这种情况的死锁,各cpu上的中断都是正常的,系统能对 ping请求作出反应,这时nml watchdog无法被触发。在2。6。16之前的内核屮
15、,并没有一 种很好的方法来处理这种情形。在rhel5, rhel6内核屮,每个cpu ±提供了一个 watchdog内核线程,在死锁出现的情况下,死锁cpu上的watchdog内核线程没法被调度(即 使它是最髙优先级的实时进程),它就没法update相应的counter变量,各cpu的nmi watchdog 中断会周期性的检查其cpu对应的counter,发现没有updated,会调用panic (),用户就 可用kdump收集内存信息,分析各死锁cpu上的调用堆栈,查处导致死锁的逻辑原因。(3) 内核的 oops 或 warningoops和warning和panic类似的地方是
16、,他们都是因内核发现了不一致而主动报告的异常。 但oops和warning导致的问题严重程度要比panic轻很多,以致于内核处理该问题时不需要使 系统挂起。产生oops和warning,内核通常已经在dmesg中记录了相当的信息,特别是oops, 至少会打印出现故障的地方的call traceo oops也可转换成panic/kdump来进行 offline-debugging,只要将/proc/sys/kernel 下的 panic_on_oops 变量设置为 1 就行了。产生oops和warning的直接原因有很多,如内核中的segment fault,或内核发现的某数 据结构的count
17、er值不对,而segment fault和counter值的变化还冇更深层次的原因,通常并 不能从内核dmesg的信息屮看出来,解决这种问题的是要用systemtap进行probe,如发现 某counter的值不对,就用systemtap做一个probe来记录所有代码对该counter的访问,然 后再进行分析。定位oops和warning会比定位应用程序的内存访问故障定位困难很多,因为在内核并不能 象用valgrind去trace应用程序一样跟踪数据结构的分配和使用情况。2、其他(硬件相关)故障机器自动重启是一种常见的故障情形,一般是由硬件如物理内存故障引起的,软件的故障只 会导致死锁或pan
18、ic,内核屮几乎没有代码在发现问题的情况下去reboot机器。在 /proc/sys/kernel冃录下有个参数panic”,其值如果设置为非0,则在panic发牛若干秒后,内 核会重启机器。现在高端的pc服务器,都在努力用软件来处理物理内存故障,如mca的 “hwpoison”方法会将故障的物理贝隔离起来,kill掉故障页所在的进程就可以了,rhel6现在 已经支持“hwpoison”。那些不具备mca能力的机器,物理内存故障时,不会产生mce异常, 直接由硬件机制reboot机器4、rhel6上的debugging技术介绍(1) kdump故障定位收集和crash分析kdump就是用来在内
19、核panic的情况下收集系统内存信息的,用户也可在online情况下用 sysrq的'c'键触发。kdump采用没有污染的内核来执行dump工作,所以其比以前的diskdump, iked方法更可靠。使用kdump,用户可选择将数据dump到本地盘或网络上,也可通过定义 makedumpfile的参数过滤要收集的内存信息,己减少kdump所需更的停机时间crash就是对kdump的信息进行分析的工具。其实际就是gdb的一个wrapper。使用crash 时,最好安装kernel-debuginfo包,这样能解析kdump收集的内核数据的符号信息。用crash 来定位问题的能力,
20、完全取决于用户对内核代码的理解和分析能力参考 “#>man kdump。conf”,“#>man crash”,u#>man makedumpfilem学习怎样使用 kdump 和 crash。访问 http: /ftp。redhato com 可下载 debuginfo 文件(2) 用 systemtap 定位 bugsystemtap属于probe类的定位工具,它能对内核或用户代码的指定位置进行probe,当执行到指定 位置或访问指定位置的数据时,用户定义的probe函数自动执行,可打印出该位置的调用堆栈,参数值, 变量值等信息。systemtap选择进行probe的位置
21、很灵活,这是systemtap的强人功能所在。systemtap 的probe点可包括如下几个方呦:内核中全部系统调用,内核及模块中全部函数的入口或出口点自定义的定时器probe点-内核屮任意指定的代码或数据访问位置-特定用户进程屮任意制定的代码或数据访问位置-各个功能子系统预先设置的若干probe点,如tcp, udp, nfs, signal各子系统都预先设置了很多探 测点systemtap的脚本用stap脚本语言来编写,脚本代码中调用stap提供的api进行统计,打印数据等 工作,关于stap语言提供的api函数,参考*#> man stapfuncs”。关于systemtap的功
22、能和使用可参考 “#man stap”, “#> man stapprobes*'(3) ftraceftrace是linux内核中利用tracepoints基础设施实现的事件追踪机制,它的作用在于能比较清楚的给 出在-定时间内系统或进程所执行的活动,如函数调用路径,进程切换流等。ftrace可用于观察系统各部 分的latency,以便进行实时应用的优化;它也可以通过记录一段时间内的内核活动来帮助故障定位。如用 以卜方法可trace某个进程在一端时间的函数调用情况1.#> echo “function” > /sys/kernel/debug/tracing/curr
23、ent_tracer2.#> echo "xxx” > /sys/kernel/debug/tracing/set_ftrace_pid3. #> echo 1 > /sys/kernel/debug/tracing/tracing_enabled除tracing函数调用外,ftrace还可tracing系统的进程切换,唤醒,块设备访问,内核数据结构分配 等活动。注意,tracing和profile是不同的,tracing fl录的是一段时间内的全部活动,而不是统计信息, 用户口j以通过/sys/kemel/debug/tracing卜-的buffer_siz
24、e_kb设置缓冲区的人小,以记录更长时间的数据。关丁 ftrace的具体使用町参考内核源码documenation/trace卜的内容(4)oprofile 和 perfoprofile和perf都是对系统进行profile (抽样,统计)的工具,它们主要用来解决系统和应用的性能 问题。perf功能更强大,更全而,同时perf的用户空间工具和内核源码一起维护和发布,让用户能及时的 享受pert内核新增加的特征。pert是在rhel6屮才有,rhel5屮没有pert oprofile和perf都使用现 代cpu中具冇的硬件计数器进行统计工作,但perf还町以使用内核中定义的“software c
25、ounter”及"trace points'*,所以能做更多的工作。oprofile的抽样工作利用cpu的nmi中断來进行,而perf既可以利用 nmi中断也可利用硬件计数器提供的周期性中断。用户能很容易用perf来oprofile -个进程或系统的执行 f寸间分布,如#> perf top -f 1000 -p还口j以利用系统定义的“software counter”和各子系统的“trace points”对子系统进行分析,女n#>perf stat -a -e kmem:mm_page_alloc -e kmem:mm_pageree_direct -e km
26、em:mmjdagevec_free sle ep 6能统计6秒内kmem子系统的活动(这一点实际是利用ftrace提供的tracepoints来实现)我认为有了 pert,用户就没必要使用oprofile 了5、用kdump工具内核故障定位实例a)部署 kdump部署kdump收集故障信息的步骤如下:(1)设置好相关的内核启动参数在/boot/grub/menu.lst中加入如下内容crashkernel=128m16m nmi_watchdog=1其中crashkernel参数是用來为kdump的内核预留内存的;nmi_watchdog=1是用来激活nmi 屮断的,我们在未确定故障是否关闭
27、了屮断的情况下,需要部署nml watchdog才能确保触发 panico重启系统确保设置生效(2)设置好相关的sysctl内核参数在/etc/sysctl.conf屮最后加入一行kernel.softlookupjdanic = 1该设置确保softlock发生时会调用panic,从而触发kdump行为执行#>sysctl -p确保设置牛效(3)配置 /etc/kdump.conf在 /etc/kdump.conf屮力fl入如下几行内容1. ext3 /dev/sdb12. core-collector makedumpfile c -message-level 7 d 31 -i /
28、mnt/vmcoreinfo3. path /var/crash4. default reboot其中/dev/sdb1是用于放置dumpfile的文件系统,dumpfile文件放置在/var/crash下,要 事先在/dev/sdb1分区下创建/var/crash目录。“d 31”指定对dump内容的过滤级别,这参数对 于dump分区放不下全部内存内容或用户不想让dumping中断业务太长时间时很重要。 vmcoreinfo文件放置在/dev/sdb1分区的/目录下,需要使用如下命令产生:#>makedumpfile -g /vmcoreinfo x /usr/lib/debug/li
29、b/modules/2.6.18-128.el5.x86_64/vmlinux“vmlinux”文件是ill kernel-debuginfo包提供的,在运行makedumpfile之前需要安装相应 内核的 kernel-debuginfo 和 kernel-debuginfo-common 两个包,该两个包需从 http: /下载。“default reboot”用来告诉kdump,收集完dump信息后重启系统。(4)激活 kdump运行#>service kdump start命令,你会看到,在成功完成的情况下会在/boot/目录下生成 一个 initrd-2o 6., 18-128
30、o el5o x86_64kdumpo img 文件,该文件就是 kdump 加载的内核的 initrd 文件,收集dump信息的工作就是在该initrd的启动环境下进行的。查看/etc/init。d/kdump脚本 的代码,你可看到其中会调用mkdumprd命令创建用于dump的initrd文件1 测试kdump部署的冇效性为了测试kdump部署的有效性,本人写了如下一个内核模块,通过insmod加载该内核模 块,就能产生一个内核线程,在10秒左右后,占据100%的cpu,在20秒左右后触发kdump., 挥统重启后,检查/oracle分区/vmr/crash冃录下的内容,就能确认vmcor
31、e文件是否生成。1 zqfthread.c #inelude2. #include3. #include4. #include5. #include6. #include7.8. module_author("frzhang");9. module_description("a module to test10. module_license(”gpl”);11.12. static struct task_struct *zqf_thread;13. static int zqfd_thread(void *data);14.15. static int zqf
32、d_thread(void *data)16. 17. inti=o;18.19. while (!kthread_should_stop() 20. i+;21. if (i<10)22. msleep_interruptible(1000);23. printk("%d seconds'”',i);24. 25. if (i = 1000 ) / running in the kernel26. i = 11 ;27. 28. return 0;29. 30. static int _init zqfinit(void)31. 32. struct task
33、_struct *p;33.34. p = kthread_create(zqfd_thread, null,"%sn,"zqfd");35.36. if ( p ) 37. zqf_thread = p;38. wake_up_process(zqf_thread); / actually start it up39. return(o);40. 41.42. return(-1);43. 44.45. static void _exit zqffini(void)46. 47. kthread_stop(zqf_thread);48. 49.50. modul
34、e_init(zqfinit);51. module_exit(zqffini)52.53. makefile obj-m += zqfthread.o54. making #> make -c /usr/src/kernels/2.6.32-71.el6.x86_64/ m='pwd' modules2、用crash工具分析vmcore文件用crash命令分析vmcore的命令行格式如下所示。用crash打开vmcore后,主要是用dmesg及bt命令打印出问题的执行路径的call trace,用dis反汇编出代码,最终确认call trace 对应的c源码中的位置,再
35、进行逻辑分析。#>crash /usr/lib/debug/lib/modules/2.6.18-128.el5.x86_64/vmlinux /boot/system.map-2.6.18-128. el5.x86_64 ./vmcore6、使用kprobe来观察内核函数的执行实例kprobe是systemtap对内核函数进行probing的功能在内核屮的实现,由于内核中提供了 正式的api來使用kprobe,所以对很多内核程序员来说,也许直接使用kprobe比使用 systemtap更方便。内核屮提供了三种类型的kprobe处理函数,分别是jprobe, kprobe, kretpr
36、obe,下面的代码用这三个probe观察在tcp/ip的arp_process函数执行中对 ipoute_input()调用的返回结果。这个代码还展示了在同一个函数probe的entry handler和ret handler之间共享参数的方法。代码如下:1. arpjdrobe.c /*2. * arp_probe.c, by qianfeng zhang (frzhang)3. 74.5. #include6 #include7. #include8. #include9. #include10. #include11. #include12. #include13.14. module_
37、author("frzhang");15. module_description("a module to track the call results of ipoutenput() insid e arp_process using jprobe and kretprobe'1);16. modulejjcense(”gpl”);17.18. static int j_arp_process(struct sk_buff *skb)19. 20. struct net_device *dev = skb->dev;21 struct in_dev
38、ice "in_dev;22. int no_addr5 rpf;23.24. in_dev = in_dev_get(dev);25. no_addr = (in_dev->ifa_list = null );26. rpf = in_dev_rpfilter(in_dev);27. in_devjdut(in_dev);28. printk(hnarp_process() is called with interface device %s, in_dev(no_ addr=%d,rpf=% d) n: dev->name, no_addr, rpf);29. jpr
39、obe_return();30. return(o);31. ;32.33 static int j_fib_validate_source(_be32 src, _be32 dst, u8 tos, int oif,34. struct net_device *dev, _be32 *spec_dst5 u32 *itag, u32 mark)35.36. 37. printk("fib_validate_source() is called with dst=0x%x, oif=%d n”,dst, oif);38. jprobe_return();39. return(o);4
40、0. ;41.42. static struct jprobe myjpl = 43. .entry = j_arp_process,44. kp.symbol_name = ,arp_process,'45. ;46.47. static struct jprobe myjp2 = 48. .entry = jib_validate_source,49. ,kp.symbol_name = "fib_validate_source"50. ;51.52. static int entry_handler(struct kretprobejnstance *ri,
41、struct pt_regs *regs)53. 54. printk("calling: %s()n", ri->rp->kp.symbol_name);55. return(o);56. ;57.58. static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)59. 60. int eax;61.62. eax = regs->ax & oxffff;63. printk("returning: %s() with a return v
42、alue: ox%仪(64bit) 0x%x(32bit)n", ri->rp->kp.sy mbol_name, regs->ax, eax);64.65. return(o);66. ;67.68. static int fib_lookup_entry_handler(struct kretprobejnstanee *ri, struct pt_regs *regs)69. 70. struct fib_result *resp;71.72. resp = (struct fib_result *) regs->dx;73. printk("
43、calling: %s()n", ri->rp->kp.symbol_name);74. *(struct fib_result *)ri->data) = resp;75.76. return(o);77. ;78.79. static int fibjookup_return_handler(struct kretprobejnstance *ri, struct pt_regs *regs)80. 81. struct fib_result *resp;82. int eax;83.84. eax = regs->ax & oxffff;85.
44、resp = *(struct fib_result *) ri->data);86. printkc'returning: fib_lookup() with a return value: 0x%lx(64bit) 0x%x(32bit), result->t ype: %dn", regs->ax, eax, resp->type);87.88. return(o);89. 90.91. static struct kretprobe my _rp1 = 92. .handler = return_handler,93. entry_handle
45、r = entry_handler,94. .kp.symbol_name = hip_route_input_slowh95. ;96.97. static struct kretprobe my ,rp2 = 98. handler = return_handler,99. .entry_handler = entry_handler,100. .kp.symbol_name = ,fib_validate_sourceh101. ;102.103 static struct kretprobe my_rp3 = 104. .handler = fib_lookup_return_hand
46、ler,105entry_handler = fib_lookup_entry_handler,106. .kp.symbol name = ”fibookupm,107. data_size = sizeof(struct fib_result *)108. ;109.110. static int _init init_myprobe(void)111. 112. int ret;113.114. printk(mrtn_unicast is %dnh, rtn_unicast);115. if (ret = registerjprobe(&myjp1) < 0) 116. printk(hregisterjprobe %s failed
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 高中化学 专题1 洁净安全的生存环境 第1单元 空气质量的改善说课稿 苏教版选修1001
- 甘肃省民勤县第五中学七年级体育《篮球(原地单手肩上投篮、变方向运球)》说课稿 新人教版
- 2025浙江嘉兴海宁市国土空间规划设计有限公司招聘1人笔试历年参考题库附带答案详解(3卷合一)
- 2025年影视导演考试题库(附答案)
- 2025年行政执行考试题库及答案
- Unit 1 My classroom Part A大单元(教学设计)-人教PEP版英语四年级上册
- 4 匀变速直线运动的速度与位移的关系说课稿-2025-2026学年高中物理人教版必修1-人教版2004
- 2025年护理生理学题库及答案68
- 2025年护考护理题库及答案大全
- 5.1.1 腔肠动物和扁形动物(说课稿)2024-2025学年八年级生物学上册同步教学(人教版河北专版)
- 造雪师培训课件
- 2025年广东省深圳市宝安外国语学校中考数学三模试卷
- 资产评估学教程(第八版)习题及答案
- 工业设计课件全套
- 道路运输企业安全生产责任制度
- 中西医结合治疗冠心病
- 膈疝介绍课件
- 注册电气工程师考试试题及答案
- 手术室护理工作中人文关怀和措施
- 2025年《儿童脑性瘫痪》标准课件
- 慢性胃炎针灸治疗
评论
0/150
提交评论