我很好奇 pstack 命令如何打印在 PID 下运行的所有线程的堆栈跟踪?
它必须与 gdb 的方式有所不同,因为进程在 gdb 环境中运行,但是 pstack 在进程执行后执行。
我在一个程序中多次调用getpid()(为了测试系统调用的效率),但是当我strace用来获取trace时,只捕获了一个getpid()调用。
代码很简单:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
void print_usage(){
printf("Usage: program count\n");
exit(-1);
}
int main(int argc, char** argv){
if(argc != 2)
print_usage();
int cnt = atoi(argv[1]);
int i = 0;
while(i++<cnt)
getpid();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我使用gdb并得到了这个:
(gdb) disasse
Dump of assembler code for function getpid:
0xb76faac0 <getpid+0>: mov %gs:0x4c,%edx
0xb76faac7 <getpid+7>: cmp $0x0,%edx
0xb76faaca <getpid+10>: mov %edx,%eax
0xb76faacc <getpid+12>: jle 0xb76faad0 <getpid+16>
0xb76faace <getpid+14>: repz ret
0xb76faad0 <getpid+16>: jne 0xb76faadc …Run Code Online (Sandbox Code Playgroud) 我收到一条消息,打印出在 ARM 平台上运行的 Linux 应用程序 (Qt C++):
未知的 HZ 值!(108) 假设 100。
此输出在不同的应用程序中定期显示,括号中的值不同。
当我从基于 glibc 的工具链切换到基于 eglibc 的工具链以构建应用程序、内核和文件系统时,它开始发生。
似乎没有造成任何不良影响,至少不是直接的。
谁能解释一下这是什么意思?
我正在使用 python ctypes 和 libc 与供应商提供的 DLL 文件进行交互。DLL 文件的目的是从相机获取图像。
图像采集似乎运行没有错误;我遇到的问题是访问数据。
图像采集函数将 ctypes.c_void_p 作为图像数据的参数。
简化如下:
"""
typedef struct AvailableData
{
void* initial_readout;
int64 readout_count;
} imageData;
"""
class AvailableData(ctypes.Structure):
_fields_ = [("initial_readout", ctypes.c_void_p),
("readout_count", ctypes.c_longlong)]
"""
Prototype
Acquire(
CamHandle camera,
int64 readout_count,
int readout_time_out,
AvailableData* available,
AcquisitionErrorsMask* errors );
"""
>>> imageData = AvailableData()
>>> Acquire.argtypes = CamHandle, ctypes.c_longlong, ctypes.c_int,
ctypes.POINTER(AvailableData), ctypes.POINTER(AcquisitionErrorsMask)
>>> Acquire.restype = ctypes.c_void_p
>>> status = Acquire(camera, readout_count, readout_time_out, imageData, errors)
Run Code Online (Sandbox Code Playgroud)
我不完全理解该函数在做什么,因为在我运行该函数后,它imageData.initial_readout似乎是一个类型“long”(甚至不是 ctypes.c_long:只是“long”)。然而,它也有一个与之相关的价值。我假设这是存储数据的起始地址。
>>> type(imageData.initial_readout)
<type …Run Code Online (Sandbox Code Playgroud) 我的 C 程序在 CentOS 5.7 上崩溃,日志如下:
kernel: [1030648.130682] myapp[16454]: segfault at 0 ip b765f683 sp bfc3fa0c error 4 in libc-2.5.so[b75ee000+157000]
Run Code Online (Sandbox Code Playgroud)
似乎对 libc 的调用导致了段错误。我如何知道段错误发生在 libc 的哪个函数中?
这是一个生产环境,没有留下任何核心转储文件;而且很少繁殖。所以,我现在能做的就是分析libc中的哪个函数(由我的程序调用)导致了这个segfault,然后我可以检查我的代码。
如果有指针可以解释这些数字的含义,那就太好了:ip b765f683, sp bfc3fa0c, error 4, b75ee000+157000。我用谷歌搜索但没有找到好的参考资料。
谢谢。
首先,一些指向 OSX 的 Libc 代码的有用链接:
在那里,可以看到 Libc 825.40.1 (OSX 10.8.5) 仍然具有像 memcpy 这样的函数的公共 asm 实现。尤其是在x86_64/string/bcopy_sse42.s. 但是,从 997.1.1 (OSX 10.9) 版本开始,它们中的大部分似乎都消失了。不过还是留了几个x86_64/string。可以在这里看到:http : //www.opensource.apple.com/source/Libc/Libc-997.90.3/x86_64/string/。
其他人的来源是否已关闭?查看 OSX 10.8 和 10.9 之间的差异并不表明它们可能已移至源代码树内部的位置。
在调试 OSX 10.9 上运行的二进制文件时,很难错过对_platform_memmove. 事实上,如果我们查看bcopy.c的源代码,我们会看到:
#include <platform/string.h>
void bcopy(const void *src, void *dst, size_t n) {
_platform_memmove(dst, src, n);
}
Run Code Online (Sandbox Code Playgroud)
所以也许这会产生一些有用的东西。然而由于某种原因,我找不到(_)platform_memmove,要么是缺乏grepping能力,要么是宏观技巧。有人可以帮我找到吗?
编辑:我尝试寻找platform/string.h,但就像那个邮件列表海报一样,我无法在源代码树中找到它。
编辑: …
通过write(或fwrite)写入的数据是否保证按顺序持久化到磁盘?特别是在容错方面。如果系统在写入期间出现故障,它是否会表现得好像首先写入第一个字节并在中途停止写入(与写入的随机块相反)。
另外,对write/ 的顺序调用是否fwrite保证是顺序的?根据 POSIX,我发现只能read保证调用write.
我在创建一个持续到磁盘的容错数据存储时询问。我的逻辑顺序是这样的,错误不会破坏数据,但如果不遵守逻辑顺序,我就会遇到问题。
注意:我不是在问是否保证持久性。只有当我对写的呼吁最终坚持下来时,他们才会遵守我实际写的顺序。
我基本上需要为我的目的定制一些linux系统调用接口(比如sys_open)。我非常了解 GNU Linker ld --wrap=符号选项并使用该逻辑来更改 open() libc 包装器。尽管这达到了目的,但我真的很想知道在 libc 源代码中的哪个位置,实际实现开始发挥作用。
以下两个地方是我的主要嫌疑人(注意fcntrl.h只有声明)
示例驱动程序:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int fd;
if ((fd = open("sample.c", O_RDONLY)) == -1) {
fprintf(stderr, "file not found\n");
exit(1);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
相关片段:
main:
401dd1: bf 44 90 48 00 mov $0x489044,%edi
401dd6: b8 00 00 00 00 mov $0x0,%eax
401ddb: e8 10 03 03 00 callq 4320f0 <__libc_open> …Run Code Online (Sandbox Code Playgroud) 我正在尝试编译使用 libdl 库中的 API 的示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int
main(int argc, char **argv)
{
void *handle;
double (*cosine)(double);
char *error;
handle = dlopen("libm.so", RTLD_LAZY);
if (!handle) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
dlerror(); /* Clear any existing error */
/* Writing: cosine = (double (*)(double)) dlsym(handle, "cos");
would seem more natural, but the C99 standard leaves
casting from "void *" to a function pointer undefined.
The assignment used below is the POSIX.1-2003 (Technical
Corrigendum 1) workaround; see …Run Code Online (Sandbox Code Playgroud) libc 的错误处理通常是< 0在发生错误时返回一些内容。我发现自己一遍又一遍地这样做:
let pid = fork()
if pid < 0 {
// Please disregard the fact that `Err(pid)`
// should be a `&str` or an enum
return Err(pid);
}
Run Code Online (Sandbox Code Playgroud)
我觉得这需要 3 行错误处理很难看,特别是考虑到这些测试在这种代码中非常频繁。
有没有办法返回一个Err以防万一fork()返回< 0?
我发现两件事很接近:
assert_eq!. 这需要另一行,panic因此调用者无法处理错误。使用这些特征:
pub trait LibcResult<T> {
fn to_option(&self) -> Option<T>;
}
impl LibcResult<i64> for i32 {
fn to_option(&self) -> Option<i64> {
if *self < 0 { None } else { Some(*self) } …Run Code Online (Sandbox Code Playgroud)