/dev/zero
0x00だけでなく、0x01から0xFFまでの任意のバイトのソースを取得できるように、ビットマスクを設定するにはどうすればよいですか?
0x00
を特定の値に変換し0x00-0xFF
ますか、それとも範囲内のランダムな値に変換しますか?
444444...
ランダムではないような特定の値にそれぞれ
/dev/zero
0x00だけでなく、0x01から0xFFまでの任意のバイトのソースを取得できるように、ビットマスクを設定するにはどうすればよいですか?
0x00
を特定の値に変換し0x00-0xFF
ますか、それとも範囲内のランダムな値に変換しますか?
444444...
ランダムではないような特定の値にそれぞれ
回答:
次のbash
コードは、バイナリで表現されているバイトで動作するように設定されています。しかし、あなたは簡単に処理するためにそれを変更することができocatal、小数や六角を単に変更することにより、基数 r
の値2
にする8
、10
または16
それぞれとの設定b=
に応じて。
r=2; b=01111110
printf -vo '\\%o' "$(($r#$b))"; </dev/zero tr '\0' "$o"
編集 - バイト値の全範囲を処理します:16進数 00 - FF(以下に00-7Fを書いたとき、シングルバイトUTF-8文字のみを検討していました)。
たとえば、4バイト(UTF-8 'ASCII'のみの16進数00-7Fの範囲の文字)のみが必要な場合は、headにパイプすることができます。... | head -c4
出力(4文字):
~~~~
出力を8ビット形式で表示するには、パイプxxd
(またはその他の1と0のバイトダンプ*)にパイプし
ます。b=10000000
および配管:... | head -c4 | xxd -b
0000000: 10000000 10000000 10000000 10000000 ....
o=$(printf ...)
2行目を書くつもりでしたか?
-v
直接の直後という名前の変数を設定するには間に合わない出力が発生します。この場合、変数の名前はo
(8進数の)- -v
オプションは(/ usr / bin / printfバージョンではなく)シェル組み込みバージョンに適用されることに注意してくださいprintf
-v
オプションは変数が指定したとおりに設定されるようにします。$(...)
最初に出力を変換します。これはなぜあるo=$(printf '\n')
のに対し、あなたが期待するかもしれない影響を与えることはありませんprintf -vo '\n'
ありません。(ここでの出力は、このような変換の影響を受けない形式であるため、ここでは重要ではありませんが、-v
オプションを知らない場合、これは知っておくと便利です。)
簡単にはできません。
そのようなデバイスを提供する独自のカーネルモジュールを作成することを検討してください。私はそれをお勧めしません。
パイプ(またはstdout
)またはFIFO に同じバイトの無限ストリームを書き込む小さなCプログラムを作成できます。
tr(1)を使用して/dev/zero
、0バイトごとに読み取り、他のバイトに変換できます。
少なくとも改行を使用する余裕がある場合は、おそらくyes(1)を使用することができます(またはパイプでtr -d '\n'
...)
yes 1 | tr -d $'\n'
その問題にします。
yes
ストリームを試みると失敗します\n
。ハンドルの選択肢は\n
次のとおりです。yes '' | tr '\n' "$c"
-どこ$c
ASCII文字の完全な範囲の任意の文字することができます。
yes 1 | tr -d $'\n'
。$''
バックスラッシュ処理を行わないシェルを使用したり、を変更するロケールを見つけようとしたりできると思いますがtr -d $'\n'
、まだ見つかりません。
yes 1 | tr -d $'\n'
ストリームと1
他のほぼすべてのシングルバイト値をかなり喜んで印刷しますが、文字のストリームを印刷することはできません\n
。OPは、「0x01と0xFFの間」の
loop() { if [ "$1" = $'\n' ]; then yes "$1"; else yes "$1" | tr -d $'\n' ; fi;
まあ、文字通りこれを達成したい場合は、LD_PRELOADフックを使用できます。基本的な考え方は、Cライブラリの関数を書き換えて、通常の関数の代わりに使用することです。
次に、read()関数をオーバーライドして、出力バッファーを0x42とXOR する簡単な例を示します。
#define _GNU_SOURCE
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <dlfcn.h>
#include <unistd.h>
static int dev_zero_fd = -1;
int open64(const char *pathname, int flags)
{
static int (*true_open64)(const char*, int) = NULL;
if (true_open64 == NULL) {
if ((true_open64 = dlsym(RTLD_NEXT, "open64")) == NULL) {
perror("dlsym");
return -1;
}
}
int ret = true_open64(pathname, flags);
if (strcmp(pathname, "/dev/zero") == 0) {
dev_zero_fd = ret;
}
return ret;
}
ssize_t read(int fd, void *buf, size_t count)
{
static ssize_t (*true_read)(int, void*, size_t) = NULL;
if (true_read == NULL) {
if ((true_read = dlsym(RTLD_NEXT, "read")) == NULL) {
perror("dlsym");
return -1;
}
}
if (fd == dev_zero_fd) {
int i;
ssize_t ret = true_read(fd, buf, count);
for (i = 0; i < ret; i++) {
*((char*)buf + i) ^= 0x42;
}
return ret;
}
return true_read(fd, buf, count);
}
単純な実装では、読み取るすべてのファイルに対してXOR 0x42が実行され、望ましくない結果が生じます。この問題を解決するために、 open()関数 / dev / zeroに関連付けられたファイル記述子をフェッチするようにしました。次に、read()関数でXORのみを実行しますfd == dev_zero_fd
。
使用法:
$ gcc hook.c -ldl -shared -o hook.so
$ LD_PRELOAD=$(pwd)/hook.so bash #this spawns a hooked shell
$ cat /dev/zero
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
速度の観点から、私が見つけた最速は:
$ PERLIO=:unix perl -e '$s="\1" x 65536; for(;;){print $s}' | pv -a > /dev/null
[4.02GiB/s]
比較のために:
$ tr '\0' '\1' < /dev/zero | pv -a > /dev/null
[ 765MiB/s]
$ busybox tr '\0' '\1' < /dev/zero | pv -a > /dev/null
[ 399MiB/s]
$ yes $'\1' | tr -d '\n' | pv -a > /dev/null
[26.7MiB/s]
$ dash -c 'while :; do echo -n "\ 1"; 完了」| pv -a> / dev / null [225KiB / s]
$ bash -c 'while :; echo -ne "\ 1"; 完了」| pv -a> / dev / null [180KiB / s]
$ < /dev/zero pv -a > /dev/null
[5.56GiB/s]
$ cat /dev/zero | pv -a > /dev/null
[2.82GiB/s]
perl
2.13GiBを< /dev/zero
生成し、8.73GiB を生成します。どのようなことがパフォーマンスに影響しますか?
perl
、他のソリューションより一貫して高速です。同等のコンパイル済みCプログラムと同じスループットが得られます。ベンチマークは、ここにあるシステムのスケジューラーと同じくらいアプリケーションにあります。最も異なるのは、書き込まれるバッファのサイズです。
cat /dev/zero| pv -a >/dev/null
毎秒約2 GiBが得られると思います(私のシステムで< /dev/zero
はそうですが、約6GiBpsになります)。
Linux ProBook 3.13.0-24-generic #47-Ubuntu SMP Fri May 2 23:30:00 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
インテルi5のコアの内部。
ビットマスク/ xorゼロバイトを試してみても意味がありませんよね?バイトを取り、xor
ゼロでそれを実行することは何もしません。
必要なバイトを提供するループを作成し、パイプまたは名前付きパイプの背後に配置するだけです。キャラクターデバイスとほぼ同じように動作します(アイドル時にCPUサイクルを浪費しません):
mkfifo pipe
while : ; do echo -n "a"; done > pipe &
また、最適化する場合は、以下のCコードを使用できます。
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
char c = argc == 1+1 ? argv[1][0] : 'y';
char buff[BUFSIZ];
memset(buff, c, BUFSIZ);
for(;;){
write(1, buff, sizeof(buff));
}
}
コンパイルして実行
$ CFLAGS=-O3 make loop
./loop "$the_byte_you_want" > pipe
性能テスト:
./loop 1 | pv -a >/dev/null
私のマシンでは2.1GB / s(さらにわずかに速いcat /dev/zero | pv -a >/dev/null
)
argc == 1+1
なくagrc == 2
?
0 XOR X == X
。
から0バイトを読み取り/dev/zero
、tr
各ゼロバイトを変換して各バイトにビットマスクを適用します。
$ </dev/zero tr '\000' '\176' | head -c 10
~~~~~~~~~~$
Octal 176はASCIIコードで~
あるため、10を取得し~
ます。($
出力の最後に、シェルで行の終わりがなかったことが示されています-あなたにとっては違って見えるかもしれません)
それでは、0xFF
バイトを作成しましょう。Hex 0xFF
は8進数0377
です。tr
コマンド行の先頭のゼロは省略されます。最後にhexdump
、出力を読み取り可能にするために使用されます。
$ </dev/zero tr '\000' '\377' | head -c 10 | hexdump
0000000 ffff ffff ffff ffff ffff
000000a
ここでは、16進数の代わりに、文字の8進数コードを使用する必要があります。したがって、範囲は\000
8進数から8進数です\377
(と同じ0xFF
)。およびを
使用ascii -x
しascii -o
て、16進数または8進数のインデックス番号を持つ文字のテーブルを取得します。
(10進数と16進数のテーブルの場合、ちょうどascii
)。
ゼロを使用するのに比べて、かなり高速に実行されますcat /dev/zero
。IOバッファリングを完全に使用できますが、tr
できません。
$ </dev/zero tr '\000' '\176' | pv -a >/dev/null
[ 913MB/s]
$ </dev/zero cat | pv -a >/dev/null
[4.37GB/s]
Infinte printfループ
必要な\u00
バイトに置き換えます。
while true ; do printf "\u00" ; done | yourapp
C ++コード:
#include<cstdio>
int main(){
char out=Byte;
while(true)
fwrite(&out,sizeof(out),1,stdout);
}
コンパイル:必要なByte
値に置き換えます。
g++ -O3 -o bin file.cpp -D Byte=0x01
つかいます
./bin | yourapp