Shell脚本中转换地址变量为数值适配dd命令的方法
问题描述
我通过Shell脚本解析/proc/PID/maps文件后,得到两个十六进制格式的地址变量:
START_ADDR=982fe000 END_ADDR=984fe000
想要将这两个变量用于以下dd命令,提取对应内存段到输出文件:
dd if=SOME_MEMORY skip=START_ADDR count=(END_ADDR-START_ADDR) of=out.bin bs=1
需要如何转换变量才能适配dd的参数要求?
解决方法
dd的skip和count参数仅接受十进制数值,但当前变量是十六进制格式,因此需要完成进制转换、地址差计算两步处理:
方式一:分步处理(用临时变量)
先将十六进制地址转成十进制,再计算内存段大小:
# 把十六进制起始地址转为十进制 START_DEC=$(printf "%d" 0x$START_ADDR) # 计算地址差并转为十进制(0x前缀让Shell识别十六进制数值) SIZE_DEC=$(printf "%d" 0x$((0x$END_ADDR - 0x$START_ADDR))) # 执行dd命令 dd if=SOME_MEMORY skip=$START_DEC count=$SIZE_DEC of=out.bin bs=1
方式二:内联计算(减少临时变量)
直接在dd命令中嵌入转换逻辑,一步执行:
dd if=SOME_MEMORY \ skip=$(printf "%d" 0x$START_ADDR) \ count=$(printf "%d" 0x$((0x$END_ADDR - 0x$START_ADDR))) \ of=out.bin bs=1
优化建议:提升读写速度
默认bs=1(单字节读写)速度极慢,建议使用页对齐的块大小(如4096),同时调整skip和count的计算方式:
BLOCK_SIZE=4096 # 计算起始块位置和总块数 START_BLOCK=$(( $(printf "%d" 0x$START_ADDR) / $BLOCK_SIZE )) SIZE_BLOCK=$(( $(printf "%d" 0x$((0x$END_ADDR - 0x$START_ADDR))) / $BLOCK_SIZE )) dd if=SOME_MEMORY skip=$START_BLOCK count=$SIZE_BLOCK of=out.bin bs=$BLOCK_SIZE
注:大部分/proc/PID/maps中的内存段是页对齐的,因此无需处理余数情况。
内容的提问来源于stack exchange,提问作者Kokomelom
相关产品推荐
相关产品推荐

