导航:首页 > 文件类型 > linux文件偏移

linux文件偏移

发布时间:2023-03-07 05:07:07

linux堆栈地址错误与报错函数偏移怎么算

一般察看函数运行时堆栈的方法是使用GDB(bt命令)之类的外部调试器,但是,有些时候为了分析程序的BUG,(主要针对长时间运行程序的分析),在程序出错时打印出函数的调用堆栈是非常有用的。

在glibc头文件"execinfo.h"中声明了三个函数用于获取当前线程的函数调用堆栈。

[cpp] view plain print?
int backtrace(void **buffer,int size)
该函数用于获取当前线程的调用堆栈,获取的信息将会被存放在buffer中,它是一个指针列表。参数 size 用来指定buffer中可以保存多少个void* 元素。函数返回值是实际获取的指针个数,最大不超过size大小
在buffer中的指针实际是从堆栈中获取的返回地址,每一个堆栈框架有一个返回地址
注意:某些编译器的优化选项对获取正确的调用堆栈有干扰,另外内联函数没有堆栈框架;删除框架指针也会导致无法正确解析堆栈内容

[cpp] view plain print?
char ** backtrace_symbols (void *const *buffer, int size)
backtrace_symbols将从backtrace函数获取的信息转化为一个字符串数组. 参数buffer应该是从backtrace函数获取的指针数组,size是该数组中的元素个数(backtrace的返回值)

函数返回值是一个指向字符串数组的指针,它的大小同buffer相同.每个字符串包含了一个相对于buffer中对应元素的可打印信息.它包括函数名,函数的偏移地址,和实际的返回地址
现在,只有使用ELF二进制格式的程序才能获取函数名称和偏移地址.在其他系统,只有16进制的返回地址能被获取.另外,你可能需要传递相应的符号给链接器,以能支持函数名功能(比如,在使用GNU ld链接器的系统中,你需要传递(-rdynamic), -rdynamic可用来通知链接器将所有符号添加到动态符号表中,如果你的链接器支持-rdynamic的话,建议将其加上!)

该函数的返回值是通过malloc函数申请的空间,因此调用者必须使用free函数来释放指针.

注意:如果不能为字符串获取足够的空间函数的返回值将会为NULL

[cpp] view plain print?
void backtrace_symbols_fd (void *const *buffer, int size, int fd)
backtrace_symbols_fd与backtrace_symbols 函数具有相同的功能,不同的是它不会给调用者返回字符串数组,而是将结果写入文件描述符为fd的文件中,每个函数对应一行.它不需要调用malloc函数,因此适用于有可能调用该函数会失败的情况

下面是glibc中的实例(稍有修改):
[cpp] view plain print?
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>

/* Obtain a backtrace and print it to @code{stdout}. */
void print_trace (void)
{
void *array[10];
size_t size;
char **strings;
size_t i;

size = backtrace (array, 10);
strings = backtrace_symbols (array, size);
if (NULL == strings)
{
perror("backtrace_synbols");
Exit(EXIT_FAILURE);
}

printf ("Obtained %zd stack frames.\n", size);

for (i = 0; i < size; i++)
printf ("%s\n", strings[i]);

free (strings);
strings = NULL;
}

/* A mmy function to make the backtrace more interesting. */
void mmy_function (void)
{
print_trace ();
}

int main (int argc, char *argv[])
{
mmy_function ();
return 0;
}
输出如下:
[cpp] view plain print?
Obtained 4 stack frames.
./execinfo() [0x80484dd]
./execinfo() [0x8048549]
./execinfo() [0x8048556]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3) [0x70a113]

我们还可以利用这backtrace来定位段错误位置。
通常情况系,程序发生段错误时系统会发送SIGSEGV信号给程序,缺省处理是退出函数。我们可以使用 signal(SIGSEGV, &your_function);函数来接管SIGSEGV信号的处理,程序在发生段错误后,自动调用我们准备好的函数,从而在那个函数里来获取当前函数调用栈。
举例如下:
[cpp] view plain print?
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <execinfo.h>
#include <signal.h>

void mp(int signo)
{
void *buffer[30] = {0};
size_t size;
char **strings = NULL;
size_t i = 0;

size = backtrace(buffer, 30);
fprintf(stdout, "Obtained %zd stack frames.nm\n", size);
strings = backtrace_symbols(buffer, size);
if (strings == NULL)
{
perror("backtrace_symbols.");
exit(EXIT_FAILURE);
}

for (i = 0; i < size; i++)
{
fprintf(stdout, "%s\n", strings[i]);
}
free(strings);
strings = NULL;
exit(0);
}

void func_c()
{
*((volatile char *)0x0) = 0x9999;
}

void func_b()
{
func_c();
}

void func_a()
{
func_b();
}

int main(int argc, const char *argv[])
{
if (signal(SIGSEGV, mp) == SIG_ERR)
perror("can't catch SIGSEGV");
func_a();
return 0;
}

编译程序:
gcc -g -rdynamic test.c -o test; ./test
输出如下:
[cpp] view plain print?
Obtained6stackframes.nm
./backstrace_debug(mp+0x45)[0x80487c9]
[0x468400]
./backstrace_debug(func_b+0x8)[0x804888c]
./backstrace_debug(func_a+0x8)[0x8048896]
./backstrace_debug(main+0x33)[0x80488cb]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0x129113]
(这里有个疑问: 多次运行的结果是/lib/i368-Linux-gnu/libc.so.6和[0x468400]的返回地址是变化的,但不变的是后三位, 不知道为什么)
接着:
objmp -d test > test.s
在test.s中搜索804888c如下:

[cpp] view plain print?
8048884 <func_b>:
8048884: 55 push %ebp
8048885: 89 e5 mov %esp, %ebp
8048887: e8 eb ff ff ff call 8048877 <func_c>
804888c: 5d pop %ebp
804888d: c3 ret
其中80488c时调用(call 8048877)C函数后的地址,虽然并没有直接定位到C函数,通过汇编代码, 基本可以推出是C函数出问题了(pop指令不会导致段错误的)。
我们也可以通过addr2line来查看
[cpp] view plain print?
addr2line 0x804888c -e backstrace_debug -f
输出:
[cpp] view plain print?
func_b
/home/astrol/c/backstrace_debug.c:57

以下是简单的backtrace原理实现:

㈡ Linux 指针偏移

你自己已经解释了呀。
为何要用char*类型的指针和unsigned long*类型的指针做运算呢?

No, 不是char*类型的指针和unsigned long*类型的指针做运算,而是char*类型的指针和unsigned long类型做运算,得到的结果还是一个指针,这才符合代码的目的(当前地址-偏移量 = 结构体指针)。如果后面是一个unsigned long*类型的指针,得到的结果就是一个偏移量,不符合代码的目的了。

㈢ 怎么消除linux下的屏幕偏移现象和调整屏幕刷新率

1、在win下调正屏幕位置,使之正中
2、启动linux,进入xwin(这时屏幕应该是歪的),开一个字符终端小窗口,运行xvidtune,用left和right按钮调好屏幕位置,再show一下,将终端窗口上显示的那一行输出记下来,类似这样的语句
"1024x768" 94.50 1024 1093 1168 1376 768 769 772 808 +hsync +vsync
3、编辑/etc/X11/XF86Config-4(或XF86Config,编辑前最好先拷贝一个作好备份)文件,找到Section "Monitor"中当前分辨率的那段,应该你会看到类似
Modeline "1024x768" 94.50 1024 1093 1168 1376 768 769 772 808 +hsync +vsync这样的语句(没有的话就将记下来的东西在开头加Modeline,将它添加到EndSection的前面),按照刚才记下来的东西修改其中的 相应位置的数值,改完后保存文件,然后重起xwindow就ok了。

(用nvidia显卡的用户请注意,如果你用系统自带的驱动按上面方 法校正了屏幕偏移现象,后来又安装nvidia显卡的驱动,则很有可能在安装完nvidia驱动后xwin启动黑屏或重新出现偏移现象,这是因为 nvidia驱动本身已经校正了屏幕偏移的问题,请将调整过偏移的那行前面加#号注释掉,譬如:

Modeline "1024x768" 94.50 1024 1093 1168 1376 768 769 772 808 +hsync +vsync改成

#Modeline "1024x768" 94.50 1024 1093 1168 1376 768 769 772 808 +hsync +vsync,再重起xwin就ok了)

注: 此方法同样可以用来调整刷新率:运行xvidtune,用中键(或左右两键一齐按下)拖动VTotal,这时会看见Vertical sync(刷新率)值会变动,调到你自己想要的值(不要太高),然后按test试一下效果,如果没问题的话,按show,再按上面的第3点同样修改 XF86Config-4(或XF86Config)文件,保存,重起xwin。

㈣ Linux编程--文件原子操作

当多个进程同时访问一个文件的时候,普通的write/read在执行的时候,无法保证操作的原子性,可能会导致文件被污染,达不到预期的结果。

任何一个需要多个函数调用的操作都不可能是原子操作,因为在两个函数调用间,内核可能会将进程挂起执行另外的进程。

如果想要避免这种情况的话,则需要使用pread/pwrite函数

ssize_t pread(int fd ,void *buffer ,size_t size,off_t offset)
返回真正读取到的字节数,offset是指的从文件开始位置起的offset个字节数开始读。其余的参数与read无异。

PS:
pread是无法中断的原子操作,无法中断它的定位和读取操作
pread读取过后的文件偏移量不会发生改变

同理pwrite也是一样的

而在文件创建的时候也是一样的,当需要做文件创建同步的时候,我们需要在O_CREATE的时候,加上O_EXCL标志位,当已经创建过的话,会返回fd,否则返回错误

int p( int filedes):
传入一个文件描述符,返回当前可用的最小文件描述符。

int p2(int filedes,int filedes2):
传入文件描述符,以及新的文件描述符,如果新的文件描述符所指向的文件已经打开,则会强行将其关闭后,将该文件描述符指向到已存在的文件描述符。
如果filedes和filedes2指向同一个文件,则不做任何处理,直接返回filedes2,不会关闭文件

新返回回来的filedes2会共享filedes的文件状态标识,文件偏移量等等信息。因为它们的文件指针会指向文件表的同一个位置。只是fd不一样而已。

㈤ 用什么linux命令能获取一个文件从某个偏移

㈥ Linux 下ELF 文件中的 .data.bss.rodata段偏移量为何相同

我明白了 .bss 段是SHT_NOBITS类,不占空间,此时.data段 size 为0 。所以三个地址也就相同了

㈦ 一个块设备,linux下怎么读取指定大小及偏移量的数据出来

使用open函数打开块设备文件,然后使用lseek函数设置偏移量,最后使用read函数读取指定的大小的数据。
三个函数的使用方法请自行搜索

㈧ 如何消除linux系统下的屏幕偏移现象

进入linux启动x在xterm里执行xvidtune,会弹出这个软件的窗口,点Auto然后点Left,Right等按钮调整你的显示器到最佳的位置,然后点界面上的Show按钮会得到类似这样的输出:
"1152x864" 121.50 1152 1232 1360 1568 864 865 868 911 +hsync -vsync

然后退出这个软件,修改你的/etc/X11/XF86Config-4文件,在:
Section "Monitor"
Identifier "AS 786T"
VendorName "Unknown"
ModelName "Unknown"
HorizSync 30 - 87
VertRefresh 50 - 160
Option "dpms"
EndSection

里加上刚才的输出:
Section "Monitor"
Identifier "AS 786T"
VendorName "Unknown"
ModelName "Unknown"
HorizSync 30 - 87
VertRefresh 50 - 160
Modeline "1152x864" 121.50 1152 1232 1360 1568 864 865 868 911 +hsync -vsync
Option "dpms"
EndSection

保存然后重起试试看。

阅读全文

与linux文件偏移相关的资料

热点内容
提取游戏文件的软件 浏览:175
基因编程是哪个专业 浏览:492
img的配置文件 浏览:422
f16的solidworks教程 浏览:797
iphone6如何设定睡眠模式 浏览:455
卖配件app都有哪些 浏览:57
discuz门户视频教程 浏览:118
javadom4j写 浏览:461
linux文件夹权限只读不能写 浏览:100
索引码表文件打开失败 浏览:399
如何改变word中所有图片的大小 浏览:200
qq绿钻帐号获取工具 浏览:47
发送文件到u盘是什么意思 浏览:765
人力资源数据分析师在哪里报考 浏览:862
java判断字节 浏览:464
文件照有角度没照好用ps怎么修补 浏览:814
嵌入式系统教程pdf 浏览:378
电视机有线怎么设置无线网络呢 浏览:228
creo怎么改配置文件中文 浏览:56
saiapp 浏览:870

友情链接