我想通过以下方式完成我在C中可以做的事情:
pread(fdesc, tgtbuf, size, file_offset);
或组合:
lseek(fd, file_offset, SEEK_SET);
read(fd, tgtbuf, size)
作为 shell命令。
对于某些尺寸/偏移,可以使用:
dd if=file bs=size skip=$((file_offset/size)) count=1
有效......但仅如果file_offset
可被size
整除。不幸的是,这对我的用例来说还不够。
我试图读取的设备以8字节为单位“阻塞”read
,但允许(需要)seek
的字节偏移。 dd
总是以bs
/ ibs
为单位,但也始终在这些单位中搜索,在我的情况下,这些单位是互斥的。
我知道我可以通过perl / python / C / ...来做到这一点 - 但有没有办法从一个简单的shell脚本中做到这一点?
编辑:因为建议在这里使用dd bs=1 count=8 ...
- 否则这不起作用。 strace
它,你会看到这样做:
$ strace -e lseek,read dd if=/dev/zero bs=1 skip=1234 count=8
[ ... ]
lseek(0, 1234, SEEK_CUR) = 0
read(0, "\0", 1) = 1
read(0, "\0", 1) = 1
read(0, "\0", 1) = 1
read(0, "\0", 1) = 1
read(0, "\0", 1) = 1
read(0, "\0", 1) = 1
read(0, "\0", 1) = 1
read(0, "\0", 1) = 1
不我需要什么 - 必须是单个 read()
。
EDIT2:
我试图读取的设备(/dev/cpu/<ID>/msr
)很奇怪,因为偏移被视为index number
,但你总是要读取8个字节,否则驱动程序在EINVAL
上提供read
但是每个索引都会返回不同的8字节值,因此您无法通过读取x+1
和x
并提取字节来“重建”来自偏移x+8
的读取。这非常不寻常......但这是/dev/cpu/<ID>/msr
在Linux中的工作方式。
答案 0 :(得分:2)
bs = size:size可以是1个字节,或者更多......(这是dd如何访问设备的指示,但对于一个文件,你可以使用你需要的任何东西......它通常更有效的读取块虽然更大的尺寸
尝试:
dd if=file bs=1 skip=whateveryouneed count=8 #to read 8 bytes starting at whateveryouneed
如果(与您在问题中的表述相反),您只能寻求8的倍数(并从那里读取8个字节):
dd if=file bs=8 skip=X count=1 #to read 8 bytes starting at whateveryouneed
#X being: whateveryouneed / 8 (ex: echo "4000 / 8" | bc )
(正如我在评论中所说,我真的很难想象一个允许你在任何地方寻找的设备,并强迫你从任何地方读取8个字节,如果任何地方也不是8的倍数......但是,嘿,一切皆有可能^^如果是这样的话,你需要另一种工具而不是dd,我很害怕)
如果确实如此奇怪:在您需要的地址周围提取2个8字节的块,然后从中提取您需要的确切部分:
blockoffset=$(($address/8))
blockstart=$(($blockoffset*8))
shift=$(($address - $blockstart))
if [ "$shift" -eq 0 ]
dd if=file bs=8 skip=$blockoffset count=1 > final
else
dd if=file bs=8 skip=$blockoffset count=2 > bigger #we read 2 blocks from blockoffset
dd if=bigger bs=1 skip=$shift count=8 > final
fi
答案 1 :(得分:1)
考虑到你已经遇到的麻烦,只需将C代码放入可执行程序即可。或者变得非常雄心勃勃,并使用“enable -f pread.so pread”将程序转换为bash扩展名
http://www.gnu.org/software/bash/manual/html_node/Bash-Builtins.html
可能超过顶部。单独的程序更容易。