如果你熟悉Linux的话,就有一个常识,Linux中所有的内存信息(进程)都是以文件形式保存在/proc目录下的,我们获取通过该目录下进程ID为名称的目录中有关该进程实时内存信息,包括网络,文件句柄、启动点、执行命令等等。本文虫虫以进程堆栈为例子,介绍通过/proc/进程号/stack文件的内容来实时跟踪进程堆栈信息。
进程阻塞为了解决这个问题,让我们考虑一个进程阻塞的过程,以TCP服务器为例。在最简单的形式中,我们可以拥有一个单线程TCP服务器,它只接收给定线程中的流量,然后处理其结果。
如上图所示,该流程有两个服务器阻塞点:accept阶段和read阶段,第一个阻塞直到客户端完成TCP握手;第二,完成TCP握手,直到数据开始读取。下面我们利用C套接字实现一个简单认证握手的过程,来模拟accept阶段的第一个阻塞过程。
使用/proc信息跟踪进程的堆栈
编译,然后运行该应用,然后知道发生阻塞,即监听完成等待连接握手。
]硬编码代码是又Linus教主去年添加的哦
查看printk格式说明符的文档,可以看到非常专业的格式:B说明符导致符号名称带有偏移量,应在打印堆栈回溯时使用。使用K说明符,用于打印应该对非特权用户隐藏的内核指针。意思是,之前你可以检索内核地址,但是现在已经屏蔽显示了,可能是为了安全的缘故。
上面的代码中我们没有使用goroutine,但是Go运行时最终会设置一个事件池文件,它允许我们监视多个文件描述符而不是单个的阻塞。
通过查看以上应用进程运行时内核被阻塞的系统调用:find/proc/$(pidofgosocket)/task-name"stack"|xargs-I{}/bin/sh-c'echo{};cat{}'...请注意,与C应用不同,我们看到了由gosocket应用的PID标识的任务组下的多个个任务的堆栈。
领取专属 10元无门槛券
私享最新 技术干货