文章每周持续更新。您的“三连冠”是对我最大的肯定。可以在微信搜索公众号“后端技术派”立即阅读(一般比博客更早更新一两篇文章)。操作系统“进程”是学生在学习计算机时必须接触到的一个基本概念。抛开那些纯理论的操作系统底层实现,这么多年一直在Linux下做软件开发。每次程序运行出现问题,我都要一步步分析进程的各种状态,找出问题出在哪里。本次柠檬将带你在Linux环境下进行实战,一步步探索解开“Linux进程”的秘密。什么是进程首先我们来说说“程序”的概念。程序是存储在磁盘上的有序指令集合,它是静态的。进程就是程序执行的过程,包括动态创建、调度、消亡的全过程。它是程序资源管理的最小单位。线程是操作系统能够进行操作调度的最小单位。在大多数情况下,它包含在流程中,是流程中的实际操作单元。一个进程可以包含多个线程,是资源调度的最小单位。《引用维基百科》查询过程的第一步,你在吗?你还好吗?psreport当前进程的快照。列出当前系统进程的快照。找到进程的PID(ProcessIDentity),pid唯一标识一个进程。使用ps命令,这个命令大家应该都知道,对于新手来说,首先他不是Photoshop。让我给你做一个简单的介绍。一般的用法是ps-ef列出系统中的常规信息,通常用管道grep出你感兴趣的进程。像这样ps-ef|grep有意思,第一列PID代表进程号,PPID(parentprocessID)代表父进程ID。探索进程的第二步,让我看看你交了哪些朋友(系统调用&信号)系统调用(systemcall)是指运行在“用户模式”下的程序从操作系统“内核模式”中请求需要更高权限才能运行的服务。系统调用提供了用户程序和操作系统之间的接口。strace后面是启动一个进程,可以跟踪进程启动后的系统调用和信号。该命令可以查看进程执行时调用了哪些系统调用。通过指定不同的选项,可以输出系统调用发生的时间,精度可以精确到微秒级,甚至可以统计分析系统的“耗时调用”,这在排查问题时非常有用进程假死问题,可以帮助你找出进程卡在了哪个系统调用上。已经运行的进程也可以像gdbattach一样指定-p参数加上pid进行attach和track。探索过程的第三步,让我看看你们带来的小弟(线程)。pstackprint正在运行的进程的堆栈跟踪打印出正在运行的进程的堆栈跟踪。执行命令pstackpid,可以看到当前线程运行的堆栈信息。pid可以通过前面的ps命令获取。pstack可以看到进程中启动的线程号,也可以看到进程中每个线程的“栈”内容到达。看到上面打印的LWP了吗,这里有一个知识点,LPW是指Light-weightprocess轻量级线程。扩展知识:Linux中没有真正的线程。Linux中没有的线程是由进程模拟的,所以称为:轻量级进程。进程是“资源管理”的最小单位,线程是“资源调度”的最小单位(这里不考虑Coroutines)探索进程的第四步,让小弟(线程)出来排队.pstreepstree-显示进程树pstree以树状结构打印正在运行的进程结构信息,可以直观的查看进程与它启动的线程的关系,并可以显示进程ID。探索进程的第五步是了解你的秘密(堆栈框架和上下文)它是死的(进程崩溃)还是活的(进程运行)。gdbgdb是GNU开发的gcc套件中Linux下的程序调试工具。您可以查看程序堆栈、设置断点、打印程序运行时信息,甚至调试多线程程序。功能非常强大。在这里把gdb当作一个命令有点大材小用。如果要详细说说gdb,完全可以撑起一篇文章的篇幅。在这里长话短说吧。有机会再开一篇文章详细介绍一下。使用gdb调试C/C++程序,首先需要在编译的时候加上-g选项,g++-gtest.cpp-otest这样生成的程序就可以用gdb调试了。可以直接使用gdb启动程序调试,也可以使用命令:gdbprog将gdb附加到一个已经启动的进程上进行调试。命令:gdbprogpid程序崩溃后,还可以用gdb调试参数corefile,看看程序死前给你留下了什么遗言(堆栈信息)。命令:gdbprogcorefile,这里需要注意一点,有些Linux系统在程序崩溃时默认不会生成corefile,这时需要ulimit-cunlimited来生成corefile。查询过程的第六步,我想知道关于你的一切。更进一步,通过/proc/pid文件了解进程的运行时信息和统计信息。/proc系统是一个伪文件系统,只存在于内存中,不占用外存空间。它以文件系统的形式提供了内核和进程之间的通信接口。进入系统/proc目录:/proc目录下有很多以数字命名的目录,每个数字代表进程号PID,即进程目录。系统中当前运行的每个进程在/proc下对应一个目录/proc/pid,以进程号作为目录名。它们是读取进程信息的接口。我们可以进入这个文件来了解进程的运行时间信息和统计信息。/proc/pid目录中有一些经常使用的重要文件。挑几个常用的说说。/proc/pid/environ包含进程的可用环境变量列表。如果程序有问题,不确定设置的环境变量是否生效,可以cat这个文件查看确认。/proc/pid/fd/该目录包含进程打开的每个文件的链接。从这里可以查看进程打开的文件描述符信息,包括标准输入、输出和错误流,以及进程打开的套接字连接文件描述符。lsof命令也有类似的效果。/proc/pid/stat包含进程的所有状态信息,进程号,父进程号,线程组号,任务运行在用户态的时间,任务运行在内核态的时间,以及进程的代码段虚拟地址空间、阻塞信号位图等。其他统计信息/proc/pid/cmdline包含用于启动进程的命令/proc/pid/cwd包含指向当前进程工作目录的链接/proc/pid/exe包含指向进程中运行的程序的链接/proc/pid/mem包含进程在内存中的内容/proc/pid/statm包含进程的内存使用信息。好吧,经过短暂的手术,您已经非常了解其过程和背后的秘密。下次我们好如果你的朋友“进程”遇到什么问题(crashcoredump、假死、阻塞、系统调用超时、文件描述符异常),你应该知道如何帮助它处理!总结一下:用ps查看进程id,进程是否还在,进程状态是否在,strace和psstack查看进程当前信息,看哪里没有卡死,对比上次调用信息每一帧找出异常点。如果进程没有了,如果有corefile,直接去gdb查看corefile信息等疑难杂症。当你怀疑进程状态信息时,看看/proc/pid下的进程状态信息,或许能给你启发。最后,如果以上都不行,闭上眼睛祈祷吧!它写在最后。今天的分享希望对你有所帮助。希望大家写的服务永不宕机,永不coredump,让上面教的操作吃灰。最后,感谢您的阅读。文章的目的是分享对知识的理解。我会反复验证技术文章,最大程度保证准确性。如果文章中有明显的错误,欢迎大家指出。我们将通过讨论共同学习。你可以在微信搜索公众号“后端技术学院”,回复“资讯”,里面有我为你准备的各种编程学习资料。文章每周持续更新,我们下期再见!参考https://man.linuxde.net/gdbhttps://blog.csdn.net/dan1518...https://blog.csdn.net/m0_3792...https://blog.csdn.net/enweite...
