嵌⼊式linux段错误,段错误调试神器-CoreDump详解
⼀、前⾔:
有的程序可以通过编译, 但在运⾏时会出现Segment fault(段错误). 这通常都是指针错误引起的. 但这不像编译错误⼀样会提⽰到⽂件某⼀⾏, ⽽是没有任何信息, 使得我们的调试变得困难起来.
gdb: 有⼀种办法是, 我们⽤gdb的step, ⼀步⼀步寻. 这放在短⼩的代码中是可⾏的, 但要让你step⼀个上万⾏的代码, 我想你会从此厌恶程序员这个名字, ⽽把他叫做调试员. 我们还有更好的办法, 这就是core file.
ulimit: 如果想让系统在信号中断造成的错误时产⽣core⽂件, 我们需要在shell中按如下设置: #设置core⼤⼩为⽆限 ulimit -c unlimited #设置⽂件⼤⼩为⽆限 ulimit unlimited 这些需要有root权限, 在ubuntu下每次重新打开中断都需要重新输⼊上⾯的第⼀条命令, 来设置core ⼤⼩为⽆限.
⽤gdb查看core⽂件: 下⾯我们可以在发⽣运⾏时信号引起的错误时发⽣core dump了. 发⽣core dump之后, ⽤gdb进⾏查看core⽂件的内容, 以定位⽂件中引发core dump的⾏. gdb [exec file] [core file] 如: gdb ./ 在进⼊gdb后, ⽤bt命令查看backtrace以检查发⽣程序运⾏到哪⾥, 来定位core dump的⽂件->⾏.
1. 什么是Core:
Sam之前⼀直以为Core Dump中Core是 Linux Kernel的意思. 今天才发现在这⾥,Core是另⼀种意思:
在使⽤半导体作为内存的材料前,⼈类是利⽤线圈当作内存的材料(发明者为王安),线圈就叫作 core ,⽤线圈做的内存就叫作 core memory。如今 ,半导体⼯业澎勃发展,已经没有⼈⽤ core memory 了,不过,在许多情况下, ⼈们还是把记忆体叫作 core 。
2. 什么是Core Dump:
我们在开发(或使⽤)⼀个程序时,最怕的就是程序莫明其妙地当掉。虽然系统没事,但我们下次仍可能遇到相同的问题。于是这时操作系统就会把程序当掉 时的内存内容 dump 出来(现在通常是写在⼀个叫 core 的 file ⾥⾯),让 我们或是 debugger 做为参考。这个动作就叫作core dump。
3. Core Dump时会⽣成何种⽂件:
Core Dump时,会⽣成诸如 core.进程号 的⽂件。
4. 为何有时程序Down了,却没⽣成 Core⽂件。
Linux下,有⼀些设置,标明了resources available to the shell and to processes。 可以使⽤#ulimit -a 来看这些设置。 (ulimit是bash built-in Command)
-a All current limits are reported
-c The maximum size of core files created
-d The maximum size of a process鈥檚 data segment
-e The maximum scheduling priority ("nice")
-f The maximum size of files written by the shell and its children
-i The maximum number of pending signals
-l The maximum size that m ay be locked into memory
-m The maximum resident set size (has no effect on Linux)
-n The maximum number of open file descriptors (most systems do not allow this value to be set)
-p The pipe size in 512-byte blocks (this may not be set)
-q The maximum number of bytes in POSIX message queues
-r The maximum real-time scheduling priority
-s The maximum stack size
-t The maximum amount of cpu time in seconds
-u The maximum number of processes available to a single user
-v The maximum amount of virtual memory available to the shell
-x The maximum number of file locks
从这⾥可以看出,如果 -c是显⽰:core file size (blocks, -c) 如果这个值为0,则⽆法⽣成core⽂件。所以可以使⽤:
#ulimit -c 1024 或者 #ulimit -c unlimited 来使能 core⽂件。
如果程序出错时⽣成Core ⽂件,则会显⽰Segmentation fault (core dumped) 。
5. Core Dump的核⼼转储⽂件⽬录和命名规则:
/proc/sys/kernel /core_uses_pid可以控制产⽣的core⽂件的⽂件名中是否添加pid作为扩展,如果添加则⽂件内容为1,否则为0
6. 如何使⽤Core⽂件:
在Linux下,使⽤:
#gdb -c core.pid program_name
就可以进⼊gdb模式。
输⼊where,就可以指出是在哪⼀⾏被Down掉,哪个function内,由谁调⽤等等。
(gdb) where
或者输⼊ bt。
(gdb) bt
7. 如何让⼀个正常的程序down:
#kill -s SIGSEGV pid
8. 察看Core⽂件输出在何处:
存放Coredump的⽬录即进程的当前⽬录,⼀般就是当初发出命令启动该进程时所在的⽬录。但如果是通过脚本启动,则脚本可能会修改当前⽬录,这时进程真正的当前⽬录就会与当初执⾏脚本所在⽬录不同。这时可以查看”/proc//cwd“符号链接的⽬标来确定进程真正的当前⽬录地址。通过系统服务启动的进程也可通过这⼀⽅法查看。
9. 嵌⼊式设备下如何使⽤Core dump:linux coredump配置与调试
Linux
⼆、Core Dump 配置与调试
<⽂件的⽣成开关和⼤⼩限制---------------------------------
1)使⽤ulimit -c 命令可查看core⽂件的⽣成开关。若结果为0,则表⽰关闭了此功能,不会⽣成core⽂件。
2)使⽤ulimit -c filesize命令,可以限制core⽂件的⼤⼩(filesize的单位为kbyte)。若ulimit -c unlimited,则表⽰core⽂件的⼤⼩不受限制。如果⽣成的信息超过此⼤⼩,将会被裁剪,最终⽣成⼀个不完整的core⽂件。在调试此core⽂件的时候,gdb会提⽰错误。
<⽂件的名称和⽣成路径----------------------------
若系统⽣成的core⽂件不带其它任何扩展名称,则全部命名为core。新的core⽂件⽣成将覆盖原来的core⽂件 。
1)/proc/sys /kernel/core_uses_pid可以控制core⽂件的⽂件名中是否添加pid作为扩展。⽂件内容为1,表⽰添加pid作为扩展名,⽣成的 core⽂件格式为;为0则表⽰⽣成的core⽂件同⼀命名为core。
可通过以下命令修改此⽂件:
echo"1" >/proc/sys/kernel/core_uses_pid
2)proc/sys/kernel/core_pattern可以控制core⽂件保存位置和⽂件名格式。
可通过以下命令修改此⽂件:
echo"/corefile/core-%e-%p-%t" >core_pattern,可以将core⽂件统⼀⽣成到/corefile⽬录下,产⽣的⽂件名为core-命令名-pid-时间戳
以下是参数列表:
%p - insert pid into filename 添加pid
%u - insert current uid into filename 添加当前uid
%g - insert current gid into filename 添加当前gid
%s - insert signal that caused the coredump into the filename 添加导致产⽣core的信号
%t - insert UNIX time that the coredump occurred into filename 添加core⽂件⽣成时的unix时间
%h - insert hostname where the coredump happened into filename 添加主机名
%e - insert coredumping executable name into filename 添加命令名
3.⽤gdb查看core⽂件:下⾯我们可以在发⽣运⾏时信号引起的错误时发⽣core dump了.
发⽣ core dump之后,⽤gdb进⾏查看core⽂件的内容,以定位⽂件中引发core dump的⾏.
gdb [exec file] [core file]
如:gdb ./
在进⼊gdb后,⽤ bt命令查看backtrace以检查发⽣程序运⾏到哪⾥,来定位core dump的⽂件->⾏.
4.开发板上使⽤core⽂件调试-----------------------------
如果开发板的操作系统也是linux,core调试⽅法依然适⽤。如果开发板上不⽀持gdb,可将开发板的环境(头⽂件、库)、可执⾏⽂件和core⽂件拷贝到PC的linux下,运⾏相关命令即可。
注意:待调试的可执⾏⽂件,在编译的时候需要加-g,core⽂件才能正常显⽰出错信息!
注意的问题:
在Linux下要保证程序崩溃时⽣成 Coredump要注意这些问题:
⼀、要保证存放Coredump的⽬录存在且进程对该⽬录有写权限。存放Coredump 的⽬录即进程的当前⽬录,⼀般就是当初发出命令启动该进程时所在的⽬录。但如果是通过脚本启动,则脚本可能会修改当前⽬录,这时进程真正的当前⽬录就会与当初执⾏脚本所在⽬录不同。这时可以查看”/proc/进程pid>/cwd“符号链接的⽬标来确定进程真正的当前⽬录地址。通过系统服务启动的进程也可通过这⼀⽅法查看。
⼆、若程序调⽤了seteuid()/setegid()改变了进程的有效⽤户或组,则在默认情况下系统不会为这些进
程⽣成Coredump。很多服务程序都会调⽤seteuid(),如MySQL,不论你⽤什么⽤户运⾏ mysqld_safe启动MySQL,mysqld进⾏的有效⽤户始终是msyql⽤户。如果你当初是以⽤户A运⾏了某个程序,但在ps⾥看到的
这个程序的⽤户却是B的话,那么这些进程就是调⽤了seteuid了。为了能够让这些进程⽣成core dump,需要
将/proc/sys/fs/suid_dumpable ⽂件的内容改为1(⼀般默认是0)。
三、这个⼀般都知道,就是要设置⾜够⼤的Core⽂件⼤⼩限制了。程序崩溃时⽣成的 Core⽂件⼤⼩即为程序运⾏时占⽤的内存⼤⼩。但程序崩溃时的⾏为不可按平常时的⾏为来估计,⽐如缓冲区溢出等错误可能导致堆栈被破坏,因此经常会出现某个变量的值被修改成乱七⼋糟的,然后程序⽤这个⼤⼩去申请内存就可能导致程序⽐平常时多占⽤很多内存。因此⽆论程序正常运⾏时占⽤的内存多么少,要保证⽣成Core⽂件还是将⼤⼩限制设为unlimited为好。
ulimit -- ⽤户资源限制命令
1、说明 :ulimit⽤于shell启动进程所占⽤的资源.
2、类别 :shell内建命令
3、语法格式 :ulimit [-acdfHlmnpsStvw] [size]
4、参数介绍 :
-H 设置硬件资源限制.
-S 设置软件资源限制.
-a 显⽰当前所有的资源限制.
-c size:设置core⽂件的最⼤值.单位:blocks
-d size:设置数据段的最⼤值.单位:kbytes
-f size:设置创建⽂件的最⼤值.单位:blocks
-l size:设置在内存中锁定进程的最⼤值.单位:kbytes
-m size:设置可以使⽤的常驻内存的最⼤值.单位:kbytes
-n size:设置内核可以同时打开的⽂件描述符的最⼤值.单位:n
-
p size:设置管道缓冲区的最⼤值.单位:kbytes
-s size:设置堆栈的最⼤值.单位:kbytes
-t size:设置CPU使⽤时间的最⼤上限.单位:seconds
-v size:设置虚拟内存的最⼤值.单位:kbytes 5,简单实例:
5、举例在Linux下写程序的时候,如果程序⽐较⼤,经常会遇到“段错误”(segmentationfault)这样的问题,这主要就是由于Linux系统初始的堆栈⼤⼩(stack size)太⼩的缘故,⼀般为10M。我⼀般把stacksize设置成256M,这样就没有段错误了!命令为:ulimit -s 262140
如果要系统⾃动记住这个配置,就编辑/etc/profile⽂件,在 “ulimit -S -c 0 > /dev/null 2>&1”⾏下,添加“ulimit -s 262140”,保存重启系统就可以了!
1] 在RH8的环境⽂件/etc/profile中,我们可以看到系统是如何配置ulimit的:
#grep ulimit /etc/profile
ulimit -S -c 0 > /dev/null 2>&1
这条语句设置了对软件资源和对core⽂件⼤⼩的设置
2] 如果我们想要对由shell创建的⽂件⼤⼩作些限制,如:
#ll h
-rw-r--r-- 1 lee lee 150062 7⽉ 22 02:39 h
#ulimit -f 100 #设置创建⽂件的最⼤块(⼀块=512字节)
#cat h>newh
File size limit exceeded
#ll newh
-rw-r--r-- 1 lee lee 51200 11⽉ 8 11:47 newh
⽂件h的⼤⼩是150062字节,⽽我们设定的创建⽂件的⼤⼩是512字节x100块=51200字节,当然系统就会根据你的设置⽣成了51200字节的newh⽂件.
3] 可以像实例1]⼀样,把你要设置的ulimit放在/etc/profile这个环境⽂件中.
⽤途:设置或报告⽤户资源极限。
语法:ulimit [ -H ] [ -S ] [ -a ] [ -c ] [ -d ] [ -f ] [ -m ] [ -n ] [ -s ] [ -t ] [ Limit ]
描述:ulimit 命令设置或报告⽤户进程资源极限,如 /etc/security/limits ⽂件所定义。⽂件包含以下缺省值极限:
fsize = 2097151
core = 2097151
cpu = -1
data = 262144
rss = 65536
stack = 65536
nofiles = 2000
当新⽤户添加到系统中时,这些值被作为缺省值使⽤。当向系统中添加⽤户时,以上值通过 mkuser 命令设置,或通过 chuser 命令更改。
极限分为软性或硬性。通过 ulimit 命令,⽤户可将软极限更改到硬极限的最⼤设置值。要更改资源硬极限,必须拥有 root ⽤户权限。
很多系统不包括以上⼀种或数种极限。 特定资源的极限在指定 Limit 参数时设定。Limit 参数的值可以是每个资源中指定单元中的数字,或者为值 unlimited。要将特定的 ulimit 设置为 unlimited,可使⽤词 unlimited。
注:在 /etc/security/limits ⽂件中设置缺省极限就是设置了系统宽度极限, ⽽不仅仅是创建⽤户时⽤户所需的极限。
省略 Limit 参数时,将会打印出当前资源极限。除⾮⽤户指定 -H 标志,否则打印出软极限。当⽤户指定⼀个以上资源时,极限名称和单元在值之前打印。如果未给予选项,则假定带有了 -f 标志。
由于 ulimit 命令影响当前 shell 环境,所以它将作为 shell 常规内置命令提供。如果在独⽴的命令执⾏环境中调⽤该命令,则不影响调⽤者环境的⽂件⼤⼩极限。以下⽰例中正是这种情况:
nohup ulimit -f 10000
env ulimit 10000
⼀旦通过进程减少了硬极限,若⽆ root 特权则⽆法增加,即使返回到原值也不可能。
关于⽤户和系统资源极限的更多信息,请参见 AIX 5L Version 5.3 Technical Reference: BaseOperating System and Extensions Volume 1 中的 getrlimit、setrlimit 或vlimit ⼦例程。
标志
-a 列出所有当前资源极限。
-c 以 512 字节块为单位,指定核⼼转储的⼤⼩。
-d 以 K 字节为单位指定数据区域的⼤⼩。
-f 使⽤ Limit 参数时设定⽂件⼤⼩极限(以块计),或者在未指定参数时报告⽂件⼤⼩极限。缺省值为 -f 标志。
-H 指定设置某个给定资源的硬极限。如果⽤户拥有 root ⽤户权限,可以增⼤硬极限。任何⽤户均可减少硬极限。
-
m 以 K 字节为单位指定物理存储器的⼤⼩。
-n 指定⼀个进程可以拥有的⽂件描述符的数量的极限。嵌入式系统是什么意思

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。