可以从shell提示符中执行相当于`pread(fd,buf,size,offset)的操作吗?

时间:2014-03-19 15:21:57

标签: shell unix sh

我想通过以下方式完成我在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+1x并提取字节来“重建”来自偏移x+8的读取。这非常不寻常......但这是/dev/cpu/<ID>/msr在Linux中的工作方式。

2 个答案:

答案 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

可能超过顶部。单独的程序更容易。