私はdd
それをソフトウェア構成制御手段として広く使用しています。これらのイメージは通常、デバイスを更新するためにフラッシュドライブに配布されます。私はしばしば画像ファイルに小さな増分更新を行い、画像全体をブロックデバイスにコピーする必要があることに気づきました。画像サイズは通常8GBなので時間がかかります。スノーモーダルとして一度組み立てられた画像は、インストールしやすい形式ではありません。つまり、ブロックで直接変更を行うことはできません。
イメージファイルをブロックデバイスと比較して、更新が必要なブロックのみを更新する方法があるかどうかを確認しています。私はこれがディスク全体に書き込むよりもはるかに速いと思います。これは、おそらく画像ファイルの10kbの増加に達するからです。
答え1
以下は、2つのファイル(ファイル1、ファイル2)をブロックごとに比較し、ブロックが異なる場合、そのブロックをファイル1からファイル2にコピーする小さなCプログラムのクイックハッキングです。ファイルやブロックデバイスでも動作します。好きなようにしてください。ただし、危険は本人負担です!
/*
Small program to blockwise compare two files and write different
blocks from file1 to file2.
Arguments: file1, file2, blocksize in bytes
If blocksize is not given, it is set to 512 (minimum)
No error checking, no intensive tests run - use at your own risk!
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(argc, argv)
int argc;
char *argv[];
{
char *fnamein; /* Input file name */
char *fnameout; /* Output file name */
char *bufin; /* Input buffer */
char *bufout; /* Output buffer */
int bufsize; /* Buffer size (blocksize) */
int fdin; /* Input file descriptor*/
int fdout; /* Output file descriptor*/
int cnt; /* Current block # */
/* Argument processing */
if (argc < 3 || argc > 4) {
fprintf(stderr,"Usage: %s infile outfile [bufsize]\n", argv[0]);
exit(1);
}
fnamein = argv[1];
fnameout = argv[2];
if (argc == 4) {
bufsize = atoi(argv[3]);
if (bufsize < 512) {
fprintf(stderr,"Error: Illegal value for [bufsize]: %s\n", argv[3]);
exit(1);
}
} else {
bufsize = 512;
}
fprintf(stderr, "Copying differing blocks from '%s' to '%s', blocksize is %i\n", fnamein, fnameout, bufsize);
if (! ((bufin = malloc(bufsize)) && (bufout = malloc(bufsize)))) {
fprintf(stderr,"Error: Can't allocate buffers: %i\n", bufsize);
exit(1);
}
fdin = open(fnamein, O_RDONLY);
if (fdin < 0) {
fprintf(stderr,"Error: Can't open input file: %s\n", fnamein);
exit(1);
}
fdout = open(fnameout, O_RDWR | O_SYNC);
if (fdout < 0) {
fprintf(stderr,"Error: Can't open ouput file: %s\n", fnameout);
exit(1);
}
cnt = 0;
while (read(fdin, bufin, bufsize) == bufsize) {
if (read(fdout, bufout, bufsize) == bufsize) {
if (memcmp(bufin, bufout, bufsize) != 0) {
fprintf(stderr, "Differing blocks at block # %i; writing block to %s\n", cnt, fnameout);
if (lseek(fdout, -bufsize, SEEK_CUR) > -1) {
if (write(fdout, bufin, bufsize) != bufsize) {
fprintf(stderr,"Error: Unable to write to output file %s block # %i\n", fnameout, cnt);
exit(1);
}
} else {
fprintf(stderr,"Error: Unable to seek to output file %s block # %i\n", fnameout, cnt);
exit(1);
}
}
} else {
fprintf(stderr,"Error: Unable to read from ouput file %s block # %i\n", fnameout, cnt);
exit(1);
}
cnt++;
}
exit(0);
}
答え2
qemu-imgを見ると、元のファイルをバックアップファイルとして使用し、qcow2形式の差分ディスクを作成します。
qemu-nbdを使用してブロックデバイスにアクセスします(nbdデバイスに変換)。
これにより、デルタがqcow2差分ディスクに書き込まれ、元のデータが保存されます。変更された各ブロックについて、差分ディスクはより小さい値だけ増加する。
その後、これらのデルタを1つ以上の「ソースファイル」に適用するには、「コミット」qemu-img操作を使用します。
答え3
まあ、あなたの質問についてのコメントで述べたように、dd
パラメータbs
、seek
およびskip
はcount
あなたの友人です。また、画像を一連の適切なサイズのチャンク(チャンクあたり10 Mbなど)に論理的に分割し、各チャンクのmd5sum(または競合が気になる場合はより長いハッシュ)を維持します。新しい画像が表示されたら、ハッシュと新しい画像を確認し(比較時間を効果的に半分に短縮し)、変更されたブロックのみをディスクにコピーします。一部のブロックは同じであり(すべてゼロである可能性があります)、それに応じて追加の最適化を実行することもできます。