ゼロ以外のバイトを取得できるように、/ dev / zeroにビットマスクをどのように配置しますか?

ゼロ以外のバイトを取得できるように、/ dev / zeroにビットマスクをどのように配置しますか?

/dev/zero0x00だけでなく、0x01と0xFFの間のすべてのバイトのソースを取得できるようにビットマスクをどのように追加しますか?

答え1

次のbashコードは、表示されたバイトで使用するように設定されています。バイナリ。しかし、簡単に変更できます。オカト少数または16進数単に変更することでカーディナリティ r2 value8または個別に設定し、10それに応じて設定します。 16b=

r=2; b=01111110
printf -vo '\\%o' "$(($r#$b))"; </dev/zero tr '\0' "$o"

編集する- それを扱う全シリーズバイト値:16進数 00-FF(以下に00-7Fを書き込むときは、シングルバイトUTF-8文字のみを考慮してください。)

たとえば、4バイトのみが必要な場合(16進00-7Fの範囲のUTF-8 'ASCII'専用文字)、パイプで接続できます。:... | head -c4

出力(4文字):

~~~~

8ビット形式で出力を表示するには、パイプxxd(または他の形式)でパイプします。1と0バイトダンプ*):
はい。b=10000000次にパイプされます。... | head -c4 | xxd -b

0000000: 10000000 10000000 10000000 10000000                    ....

答え2

これは簡単にできません。

これらのデバイスを提供するために独自のカーネルモジュールを作成することを検討することができます。私はこれをお勧めしません。

一部のパイプ(OR)またはFIFOに同じバイトの無限ストリームを書き込む小さなCプログラムを書くことができますstdout

使用できるTR(1)各0バイトを読み取り、/dev/zero別のバイトに変換します。

あなたは使用することができますそれは1)、少なくとも改行を余裕があれば(またはパイプでtr -d '\n'...)

答え3

まあ、もし文字通りこれを達成するには、次のものを使用できます。LD_PRELOADフック。基本的な考え方は、Cライブラリの関数をオーバーライドして、通常の関数の代わりに使用することです。

これは書き直す簡単な例です。読む()この関数は出力バッファを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として扱うので、望ましくない結果につながる可能性があります。この問題を解決するために私も電話を切った。開いている()/dev/zero に関連付けられたファイル記述子を取得する関数です。それから私達は私達の仕事だけ読む()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

答え4

ビットマスク/ 0バイト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/秒マイコンピュータでは(より少し高速ですcat /dev/zero | pv -a >/dev/null

関連情報