Linux 报错代码 139 解析与修复方法 (linux error code 139)

Linux 是一款非常稳定可靠的操作系统,但是随着软件的不断升级和各种应用程序的普及,Linux 报错也日益常见,比如常见的 139 错误码。这个错误通常与应用程序错误或者是系统库错误有关,下面我们将对 Linux 报错代码 139 进行详细解析,并提供一些修复方法。

Linux 报错代码 139 的含义

Linux 报错代码 139 通常表示应用程序中的段错误(Segmentation Fault),也就是程序试图读取或写入非法的内存位置,导致程序崩溃。这个错误码还有其他的含义,比如在某些高级语言中,它可能表示运行时错误。

造成这个错误的原因很多,可能是代码中的指针错误、数组越界、缓冲区溢出、堆栈溢出等。当程序试图访问无效的内存地址时,内核会检测到这个情况,并发送一个信号给应用程序,告诉它出现了段错误。然后应用程序将会停止并退出。

常见的修复方法

虽然 Linux 报错代码 139 可能是一个非常恼人的问题,但是通常来说这个问题是可以解决的。下面我们提供一些常见的修复方法。

1. 检查代码

我们需要检查应用程序的代码。如果应用程序在使用指针时没有正确检查是否空,或者在使用数组时没有检查数组下标是否越界,这可能会导致 Linux 报错代码 139。因此,我们需要仔细检查代码并修复潜在的错误。

2. 检查系统库

有时候,Linux 报错代码 139 可能是由于系统库中的错误引起的。这时候,我们需要检查系统库是否正确安装、更新和配置。如果系统库存在问题,可以尝试重新安装、更新或者更改配置来解决问题。

3. 调试应用程序

在调试应用程序时,我们可以使用 gdb 工具来了解程序在崩溃时发生了什么。通过 gdb,我们可以查看程序状态、变量值、堆栈信息等,找到导致 Linux 报错代码 139 的根本原因,并尝试解决它。

4. 优化编译器选项

有时候,使用不正确的编译选项可能会导致 Linux 报错代码 139。例如,过度优化代码可能会导致指针和数组访问错误。因此,我们需要使用正确的编译器选项来编译应用程序。

5. 使用内存检测工具

我们可以使用内存检测工具来帮助我们找到代码中的内存访问错误。常见的工具包括 Valgrind、Memtest86 等。这些工具可以检测内存访问错误,并帮助我们尽早发现和解决这些问题。

Linux 报错代码 139 可能是一个非常令人沮丧的问题,但是通过一些简单的方法,我们可以找到并解决这些问题。对于开发人员来说,请确保程序代码没有内存访问错误,并使用正确的编译选项来编译应用程序。对于系统管理员来说,请确保系统库正确安装、更新和配置好,并使用内存检测工具来帮助找到和解决内存访问错误。通过这些方法,我们可以提高 Linux 系统的稳定性和可靠性,为用户提供更好的服务。

相关问题拓展阅读:

  • 关于Linux中禁用中断和锁定的关系问题

关于Linux中禁用中断和锁定的关系问题

禁用了中断后就不会发生抢占了,抢占是通过中断来实现的。

你可以参考一下

一个硬中断的完整处理过程(2.4.24版本) CPU做的搜余工作:

CPU收到中断/异常信号;

CPU判断当前CPL级别如果等于3,则导致堆栈切换3->0,堆栈切换过程:

a. CPU从当前TR指向的TSS中读取SS0和ESP0;

b. CPU将当前的【SS:ESP】寄存器内容临时保存起来,假设为SSt和ESPt;

c. CPU将SS0和ESP0恢复到【SS:ESP】寄存器中;

d. CPU将在b中临时保存的SSt和ESPt压入当前的堆栈【SS:ESP】中世伏滚(其实就是SS0和ESP0);

CPU判断当前CPL级别如果等于0,则不会有2中的步骤;

CPU将EFLAGS、CS、EIP依次压入当前的堆栈【SS:ESP】中;

如果当前是异常,则CPU将异常码error code压入当前的堆栈【SS:ESP】中,否则会省略该步骤;

对于中断,CPU清零当前EFLAGS->IF位,即关闭CPU中断使能,对于异常,CPU则不会清零该位;

执行对中断/异常处理程序的调用;

注:对中断/异常处理程序的要求,为了正常的从中断/异常处理程序中返回,中断/异常处理程序必须使用IRET指令返回,该指令会依次出栈EIP、CS和EFLAGS,比RET多一个EFLAGS,当EFLAGS恢复后,由于原来保存时IF位为1,因厅岁此这里相当于CPU中断使能又打开了;

Linux内核做的工作:

1. 中断向量表–>common_interrupt:

common_interrupt:

SAVE_ALL

pushl $ret_from_intr

SYMBOL_NAME_STR(call_do_IRQ):

jmp SYMBOL_NAME_STR(do_IRQ);

SAVE_ALL保存所有CPU没有保存的寄存器,由于do_IRQ是函数,这里直接调用jmp,(一般用call来调用函数,call会导致pushEIP,但jmp不会)这样当do_IRQ返回调用ret(ret相当于popEIP)时,会弹出栈中最后一个元素到EIP,很显然这里就是ret_from_intr,也就是说,从do_IRQ中返回后,会跳转到ret_from_intr处继续执行;

2. 来到do_IRQ:

a. 首先给硬中断计数加1,irq_enter(cpu, irq)也就是:++local_irq_count(cpu);每进入一个硬中断处理函数前,local_irq_count(cpu)计数便被加1,处理完毕后减1;

b. 如果当前设备中断处理函数可以在中断打开的情况下运行,则调用sti将EFLAGS.IF置位,打开硬中断使能;

c. 调用request_irq注册的设备硬中断处理函数;

d. 无论EFLAGS.IF是否为0,都调用cli将EFLAGS.IF清零,将硬中断使能关闭;

e. 给硬中断计数减1,irq_enter(cpu, irq);该函数其实就是:–local_irq_count(cpu);

f. 如果此时有软中断需要运行(如在前面的硬中断处理函数中调用__cpu_raise_softirq),则进入do_softirq中处理软中断,关于do_softirq中的处理步骤见3;

e. do_IRQ执行ret,返回到ret_from_intr。

3. do_softirq:

a. 首先判断当前是否还有没有处理完毕的硬中断处理程序或软中断处理程序,如果有,则直接退出该函数。判断方法见附注【文(6)】。

b.将软中断处理计数加1,local_bh_disable()也就是local_bh_count(cpu)++;每进入do_softirq准备进行处理软中断前,local_bh_count(cpu)计数便被加1,软中断处理函数处理完毕后,在do_softirq返回前,将其值减1;

c. 无论EFLAGS.IF是否为0,都调用cli将EFLAGS.IF清零,将硬中断使能关闭,处理些软中断标志位的问题,随后调用sti将EFLAGS.IF置位,打开硬中断使能;

d. 执行软中断处理函数;

e. 调用cli将EFLAGS.IF清零,将硬中断使能关闭,处理些软中断标志位的问题;

f. 将软中断处理计数减1,local_bh_enable()也就是local_bh_count(cpu)–;

g. 返回到2.e中;

4. ret_from_intr:

ENTRY(ret_from_intr)

GET_CURRENT(%ebx)

movl EFLAGS(%esp),%eax

movb CS(%esp),%al

testl $(VM_MASK | 3),%eax

jne ret_with_reschedule

jmp restore_all

在这段代码中,通过”testl $(VM_MASK |3),%eax”检测中断前夕寄存器EFLAGS的高6位和代码段寄存器CS的内容,来判断中断前夕CPU是否运行于VM86模式、用户空间还是系统空间,对VM86这里不讲了,但是我们知道CS更低两位代表着中断发生时CPU的运行级别CPL,我们知道Linux只采用两种运行级别,系统为0,用户为3,所以,如果CS的更低两位为非0,那就说明中断发生于用户空间。如果中断发生于系统空间,控制就直接转移到restore_all,而如果发生于用户空间,则转移到ret_with_reschedule。在restore_all中恢复1中保存的寄存器,随后调用iret恢复EIP、CS、EFLAGS返回到中断发生时的状态。

5. ret_with_reschedule:

a. 如果发现当前进程的need_resched==1,则会调用schedule;

b. 如果发现还有待需要处理的软中断,则会调用do_softirq;

说明:能够走到ret_with_reschedule处,从4中可知,该中断前一定位于用户层,而且不可能有可中断的硬中断或软中断没有执行,也就是说到达这里in_interrupt必然为0。为什么这里要说不可能有可中断的硬中断或软中断没有执行呢?可中断的硬中断或软中断必然是被中断或者异常所打断的,当后者处理完毕后,从4中可知,由于后者发生前位于内核态(也就是可中断的硬中断或软中断处理过程中的那个点),故控制就直接转移到restore_all,即返回到了可中断的硬中断或软中断被打断时的那个点,继续处理完毕,可见,到达这里,必然不存在可中断的硬中断或软中断未被执行。

附注:关于in_interrupt宏,也就是(local_irq_count(__cpu) +local_bh_count(__cpu) !=0)。什么情况下会导致进入do_softriq时,in_interrupt不为0呢?之一种,如果当前正在处理可中断的硬中断处理函数,假设此时来了另一个通道的硬中断,将导致当前硬中断处理函数被中断,进入do_IRQ,随后处理新来的硬中断处理函数,当处理完毕后,到达do_softirq,由2中可知,此时local_irq_count(__cpu)被原先的硬中断加1,由于其还没有处理完毕,故–local_irq_count(cpu)还没来得及执行,因此local_irq_count(__cpu)>0,也就是in_interrupt!=0;第二种,如果当前正在do_softirq中处理软中断处理函数,现在来了个硬中断,将导致当前硬中断处理函数被中断,进入do_IRQ,随后处理新来的硬中断处理函数,当处理完毕后,又来带到了do_softirq,由3中可知,此时local_bh_count(cpu)被前一个do_softirq加1了,但是由于其是中途被中断的,故local_bh_count(cpu)–还没来得及执行,因此local_bh_count(__cpu)>0,也就是in_interrupt!=0;第三种就是综合之一种和第二种两种情况。

首先原子操作是通过local_irq_enable()这个宏来实现,这个宏实现了硬件中断和软件中断的屏蔽。这样CPU就不能被软件中断,如线程抢占。而当硬件中断产生时,会将其结果保存到中断控制器的SRCPND(resource-pend)寄存器中,然后将SRCPND的内容送去做中断屏蔽检测,这一工作由设置MASK寄存器伏神手相应的位完成缺嫌,如果全部屏蔽,硬件中断就不会产生了。当然了,每种处理瞎孝器都有自己的中断处理方法,通常的流程是这样。

关于linux error code 139的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

版权声明:本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
文章名称:《Linux 报错代码 139 解析与修复方法 (linux error code 139)》
文章链接:https://zhuji.vsping.com/33119.html
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。