网上看到一个很有意思的美团面试题:为什么线程崩溃崩溃不会导致 JVM 崩溃,这个问题我看了不少回答,但发现都没答到根上,所以决定答一答,相信大家看完肯定会有收获,本文分以下几节来探讨
我们经常会使用 kill 命令杀掉运行中的进程,对多次杀不死的进程进一步用 kill -9 干掉它。你可能知道这是在用 kill 命令向进程发送信号,优雅或粗暴的让进程退出。我们能向进程发送很多类型的信号,其中一些常见的信号 SIGINT 、SIGQUIT、 SIGTERM 和 SIGKILL 都是通知进程退出,但它们有什么区别呢?很多人经常把它们搞混,这篇文章会让你了解 Linux 的信号机制,以及一些常见信号的作用。
panic 究竟是啥?看似显而易见的问题,但是却回答不出个所以然来。奇伢分两个章节来彻底搞懂 panic 的知识:
SIGSEGV,也称为分段违规或分段错误,是基于 Unix 的操作系统(如 Linux)使用的信号。它表示程序尝试在其分配的内存之外进行写入或读取,由于编程错误、软件或硬件兼容性问题或恶意攻击(例如缓冲区溢出)。
Linux进程间通信(Inter-Process communication, IPC)机制通常分6种:
目前 Linux 支持64种信号。信号分为非实时信号(不可靠信号)和实时信号(可靠信号)两种类型,对应于 Linux 的信号值为 1-31 和 34-64。
fork()是一个绝对唯一的调用。Python中的大多数函数会之返回一次,因为sys.exit()会终止程序,所以它就不会返回。相比之下,Python的os.fork()是唯一返回两次的函数,任何返回两次的函数,在某种意义上,都可以调用os.fork()来实现。在调用fork()之后,就同时存在两个正在运行程序的拷贝。但是第二个拷贝并不是从开始就重新开始的。两个拷贝在对fork()调用后会继续——进程的整个地址空间被拷贝。这时可能会出现错误,而os.fork()可以产生异常。
有些 BUG 是业务逻辑上的错误导致的,一般不会导致程序崩溃,例如:原本要将两个数相加,但不小心把这两个数相减,而导致结果出错。这时我们可以通过在程序中,使用 printf 这类输出函数来进行打点调试。
当容器终止时,容器引擎使用退出码来报告容器终止的原因。如果您是 Kubernetes 用户,容器故障是 pod 异常最常见的原因之一,了解容器退出码可以帮助您在排查时找到 pod 故障的根本原因。
当我们使用kill命令发送或者在终端按下ctrl+c时,我们编写的中断处理函数就会收到中断信号
呵,段错误?自从我看了这篇文章,我还会怕你个小小段错误? 请打开你的Linux终端,跟紧咯,准备发车!!嘟嘟嘟哒~~
的过渡称为控制转移(control transfer)。这样的控制转移序列叫做处理器的控制流(flow of control or control flow) control flow的突变(
进程间通信方式有多种,其中软中断通信是一种常见的方式,它基于信号机制,可以在不同进程之间进行通信。软中断通信的实现方式是,一个进程向另一个进程发送一个特定的信号,该信号被接收进程捕获,并进行相应的处理。
一、背景 在Android平台,native crash一直是crash里的大头。native crash具有上下文不全、出错信息模糊、难以捕捉等特点,比java crash更难修复。所以一个合格的异常捕获组件也要能达到以下目的: 支持在crash时进行更多扩展操作,如: 打印logcat和应用日志 上报crash次数 对不同的crash做不同的恢复措施 可以针对业务不断改进和适应 二、现有的方案 其实3个方案在Android平台的实现原理都是基本一致的,综合考虑,可以基于coffeecatch改进。
在操作系统中,进程之间需要进行通信以实现协作和数据共享。以下是几种常见的进程通信方式:1)管道(Pipe):管道是一种半双工的通信方式,它可以在两个进程之间传递数据。管道的特点是数据只能单向流动,而且通常只用于具有亲缘关系的进程之间进行通信,例如父子进程之间。
gRPC 1.23.0 发布了。gRPC 是 Google 开源的高性能、通用 RPC 框架,面向移动和 HTTP/2 设计,是由谷歌发布的首款基于 Protocol Buffers 的 RPC 框架。gRPC 基于 HTTP/2 标准设计,带来诸如双向流、流控、头部压缩、单 TCP 连接上的多复用请求等特性。这些特性使得其在移动设备上表现更好,更省电且节省空间占用。
虽然说 PHP 是世界上最好的语言,但是对于 PHPer 们来说,对多进程、进程管理还是相对陌生的。本文将讲解一下使用 PHP 原生代码如何实现多进程。
aio_return 异步 I/O 和标准块 I/O 之间的另外一个区别是我们不能立即访问这个函数的返回状态,因为我们并没有阻塞在 read 调用上。在标准的 read 调用中,返回状态是在该函数返回时提供的。但是在异步 I/O 中,我们要使用 aio_return 函数。这个函数的原型如下: ssize_t aio_return( struct aiocb *aiocbp ); 只有在 aio_error 调用确定请求已经完成(可能成功,也可能发生了错误)之后,才会调用这个函数。aio_return 的返回值就等价于同步情况中 read 或 write 系统调用的返回值(所传输的字节数,如果发生错误,返回值就为 -1)。 aio_write aio_write 函数用来请求一个异步写操作。其函数原型如下: int aio_write( struct aiocb *aiocbp ); aio_write 函数会立即返回,说明请求已经进行排队(成功时返回值为 0,失败时返回值为 -1,并相应地设置 errno)。 这与 read 系统调用类似,但是有一点不一样的行为需要注意。回想一下对于 read 调用来说,要使用的偏移量是非常重要的。然而,对于 write 来说,这个偏移量只有在没有设置 O_APPEND 选项的文件上下文中才会非常重要。如果设置了 O_APPEND,那么这个偏移量就会被忽略,数据都会被附加到文件的末尾。否则,aio_offset 域就确定了数据在要写入的文件中的偏移量。 aio_suspend 我们可以使用 aio_suspend 函数来挂起(或阻塞)调用进程,直到异步请求完成为止,此时会产生一个信号,或者发生其他超时操作。调用者提供了一个 aiocb 引用列表,其中任何一个完成都会导致 aio_suspend 返回。 aio_suspend 的函数原型如下: int aio_suspend( const struct aiocb *const cblist[], int n, const struct timespec *timeout ); aio_suspend 的使用非常简单。我们要提供一个 aiocb 引用列表。如果任何一个完成了,这个调用就会返回 0。否则就会返回 -1,说明发生了错误。请参看清单 3。 清单 3. 使用 aio_suspend 函数阻塞异步 I/O struct aioct *cblist[MAX_LIST] /* Clear the list. */ bzero( (char *)cblist, sizeof(cblist) ); /* Load one or more references into the list */ cblist[0] = &my_aiocb; ret = aio_read( &my_aiocb ); ret = aio_suspend( cblist, MAX_LIST, NULL ); 注意,aio_suspend 的第二个参数是 cblist 中元素的个数,而不是 aiocb 引用的个数。cblist 中任何 NULL 元素都会被 aio_suspend 忽略。 如果为 aio_suspend 提供了超时,而超时情况的确发生了,那么它就会返回 -1,errno 中会包含 EAGAIN。 aio_cancel aio_cancel 函数允许我们取消对某个文件描述符执行的一个或所有 I/O 请求。其原型如下: int aio_cancel( int fd, struct aiocb *aiocbp ); 要取消一个请求,我们需要提供文件描述符和 aiocb 引用。如果这个请求被成功取消了,那么这个函数就会返回 AIO_CANCELED。如果请求完成了,这个函数就会返回 AIO_NOTCANCELED。 要取消对某个给定文件描述符的所有请求,我们需要提供这个文件的描述符,以及一个对 aiocbp 的 NULL 引用。如果所有的请求都取消了,这个函数就会返回 AIO_CANCELED;如果至少有一个请求没有被取消,那么这个函数就会返回 AIO_NOT_CANCELED;如果没有一个请求可以被取消,那么这个函数就会返回 AIO_ALLDONE。我们然后可以使用 aio_error 来验证每个 AIO 请求。如果这个请求已经被取消了,那么 aio_error 就会返回 -1,并且 errno 会被设置为 ECANCELED。 lio_listio 最后,AIO 提供了一种方法使用 lio_listio API 函数同时发起多个传输。这个函数非常重要,因为这意味着我们可以在一个系统调用(一次内核上下文切换
信号是由操作系统传给进程的中断,会提早终止一个程序。在 UNIX、LINUX、Mac OS X 或 Windows 系统上,可以通过按 Ctrl+C 产生中断。
约定:对gdb的命令,如果有缩写形式,会在第一次出现的时候小括号内给出缩写,比如运行命令写成run(r);本文中尖括号< >用来表达一类实体,比如<program>表示这个地方可以放置程序;中括号[]表示括号中的内容是可写可不写,比如[=<value>],表示“=<value>”可以有也可以没有(<value>本身又是一类实体);“|”表示或的关系。
揭秘Crashpad系统如何帮助Dropbox这样复杂的桌面程序捕获并报告崩溃,且兼容Python的多种语言。
最近,Rust 已成为安全系统级编程的有前途的替代方案。在为程序员提供细粒度的硬件控制的同时,其强类型系统强制执行许多安全属性。然而,Rust 的安全保证不是灵丹妙药。正如大量研究报告的那样,运行时崩溃和内存安全错误仍然困扰着 Rust 开发人员,导致破坏性的可利用漏洞。在本文中,我们通过对 Rust 执行静态分析,展示并评估了一个用于 Rust 程序的全自动错误检测框架 -- MirChecker 。基于对 Rust 代码库中发现的现有错误的观察,MirChecker 的方法会跟踪数字和符号信息,通过使用约束求解技术检测潜在的运行时崩溃和内存安全错误,并向用户输出信息性诊断信息。我们的实验表明 MirChecker 可以检测我们代码片段中的所有问题,并且能够在实际场景中执行错误查找, -- https://mssun.me/research/ccs21mirchecker.html
linux 进程在树中排序。每个进程都可以产生子进程,并且除了最顶层的进程之外,每个进程都有一个父进程。
什么是信号 软中断信号(signal,又简称为信号)用来通知进程发生了异步事件。在软件层次上是对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。信号是进程间通信机制中唯一的异步通信机制,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。进程之间可以互相通过系统调用kill发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。信号机制除了基本通知功能外,还可以传递附加信息。 收到信号的进程对各种信号有不同的
异常控制流(Exceptional Control Flow,ECF)是操作系统为应用提供的一种访问处理器资源之外的能力,对应于嵌入式和CPU等硬件的中断概念。 系统调用,进程管理,并发,IO 访问都属于异常控制流。 异常(exception)是控制流的突变,用来处理处理器状态中的某些变化。异常通过事件(event)触发,有专门的异常表(exception table)用于事件的跳转。 每种类型的异常都有唯一的异常号(exception number),有可能是处理器设计时分配的零除,缺页
前言 unix提供的IO模型有几种,分别有哪些? 各种IO模型的特点是什么?他们有什么区别? 阻塞,非阻塞,同步,异步的区别? epoll为什么高效? 概述 普通输入操作包含的步骤 等待数据准备好 从内核向进程复制数据 网络数据输入包含的步骤 等待数据从网络送达,到达后被复制到内核缓冲区 把数据从内核缓冲区复制到应用程序缓冲区 IO模型介绍 阻塞式IO 使用系统调用,并一直阻塞直到内核将数据准备好,之后再由内核缓冲区复制到用户态,在等待内核准备的这段时间什么也干不了 下图函数调用期间,一直被阻塞,直到数据准
SIGINT的默认处理动作是终止进程,SIGQUIT的默认处理动作是终止进程并且Core Dump,现在我们来验证一下。
一个套接字的输入操作,第一步是等待数据到达网络,当分组到达时,它被拷贝到内核中的某个缓冲区,第二步是将数据从内核缓冲区拷贝到应用缓冲区
使用gdb进行调试后,定位到错误。当程序执行 return 1 + my_strlen(p++)这条语句时,会出现以下的段错误情况。
注: 此系列内容来自网络,未能查到原作者。感觉不错,在此分享。不排除有错误,可留言指正。
数字信号处理中的量化指将输入信号从一个大的集合映射到一个的小集合的过程。可以简单的、狭义的理解为将一个连续的量映射到离散的集合上的过程。如下图所示,红色曲线是输入信号,通过3比特量化得到的结果为蓝色曲线。
Backtrace中,一般都只有一些地址。但是利用addr2line这个工具,就可以找到对应的代码行。前提条件是可执行程序或者动态链接库编译的时候带-g选项。
1. 关于信号这个话题我们其实并不陌生,早在以前的时候,我们想要杀死某个后台进程的时候,无法通过ctrl+c热键终止进程时,我们就会通过kill -9的命令来杀死信号。 查看信号也比较简单,通过kill -l命令就可以查看信号的种类,虽然最大的信号编号是64,但实际上所有信号只有62个信号,1-31是普通信号,34-64是实时信号,这篇博文不对实时信号做讨论,只讨论普通信号,感兴趣的老铁可以自己下去研究一下。
应用程序中存在多个线程会带来有关从多个执行线程安全访问资源的潜在问题。修改同一资源的两个线程可能会以意想不到的方式相互干扰。例如,一个线程可能会覆盖另一个线程的更改或将应用程序置于未知且可能无效的状态。如果幸运的话,损坏的资源可能会导致明显的性能问题或崩溃,这些问题相对容易追踪和修复。但是,如果您不走运,损坏可能会导致微妙的错误,这些错误直到很久以后才会显现出来,或者这些错误可能需要对您的基本编码假设进行重大检查。
欢迎来到 Angrave 的众包系统编程维基书!这个维基是由伊利诺伊大学的学生和教师共同建立的,是伊利诺伊大学 CS 的 Lawrence Angrave 的众包创作实验。
一、函数原型:sigaction函数的功能是检查或修改与指定信号相关联的处理动作(可同时两种操作)
trap命令是Shell内建命令,用于指定在接收到信号后将要采取的动作。常见的用途是在脚本程序被中断时完成清理工作。
网上很多文章都说,线程比较轻量级 lightweight,进程比较重量级,首先我们来看看这两者到底的区别和联系在哪里。
在使用C或C++编写程序时,有时会遇到一些运行时错误,其中一种常见的错误是Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0。这个错误提示意味着程序引发了一个严重的信号(Signal),导致程序崩溃。SIGSEGV是段错误(Segmentation Fault)的信号,它通常发生在访问无效的内存地址时。
管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。
函数调用若内核无数据准备好返回EWOULDBLOCK错误,若内核数据准备好则将数据拷贝到应用缓冲区,返回成功指示;
导语:这是篇读书笔记,每次重读CSAPP都有新的认知,尤其是在进入了后台通道之后才感受到每天和进程打交道的感觉是如此深刻。 0x00 What is Process? [ system structure ] 进程(Process) 经典定义是一个执行中的程序的实例,操作系统对一个正在运行的程序的一种抽象。并发运行,指的是一个进程的指令和另一个进程的指令交错执行。操作系统实现这种交错执行的机制称为上下文切换。 线程(Thread) 一个进程可以由多个线程的执行单元组成,每个线程都运行在进程的
本文主要分析Go语言的panic/recover在AMD64 Linux平台下的实现,包括:
问: Segmentation fault 可以用程序被捕获吗? 答:不能防不胜防: 换个问题:谈谈你段错误理解, 如果是回答 core,非法地址, 说明还是处于青铜阶段,这是定义, 根本不知道背
Notify函数让signal包将输入信号转发到c。如果没有列出要传递的信号,会将所有输入信号传递到c;否则只传递列出的输入信号。
英文:Julia Evans,编译:Linux中国 / jessie-pang linux.cn/article-9256-1.html 本文是关于 fork 和 exec 是如何在 Unix 上工作的。你或许已经知道,也有人还不知道。几年前当我了解到这些时,我惊叹不已。 我们要做的是启动一个进程。我们已经在博客上讨论了很多关于系统调用的问题,每当你启动一个进程或者打开一个文件,这都是一个系统调用。所以你可能会认为有这样的系统调用: start_process(["ls","-l","my_cool_dir
当异常发生时,Linux内核给造成异常的进程发送一个信号,告知其发生了异常。比如,如果一个进程尝试除零操作,CPU会产生除法错误异常,相应的异常处理程序发送SIGFPE信号给当前进程,然后由其采取必要的步骤,恢复还是中止(如果该信号没有对应的处理程序,则中止)。
2012 年 7 月写这篇文章,我已经有大约一年没有运行 WRF了。或许我在本文中所写的内容已过时,它只包含当 WRF 不运行时可以尝试的方法。我感觉到你的痛苦,但我无法让它消失。对不起,我希望我能知道更多,以便我可以给你提供帮助。
领取专属 10元无门槛券
手把手带您无忧上云