[unix] 0이 아닌 바이트를 얻을 수 있도록 / dev / zero에 비트 마스크를 어떻게 넣을 수 있습니까?

비트 마스크를 어떻게 설정 /dev/zero하여 0x00뿐만 아니라 0x01과 0xFF 사이의 바이트에 대한 소스를 가질 수 있습니까?



답변

다음 bash코드는 이진수 로 표현되는 바이트와 작동하도록 설정되어 있습니다 . 그러나 당신은 쉽게 처리하기 위해 변경할 수 있습니다 ocatal , 진수 또는 진수를 단순히 변경하여 기수 r 의 값 2 에를 8, 10또는 16각각 및 설정에 b=따라.

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

편집모든 바이트 값 범위 를 처리 합니다 : 16 진수 00FF (아래에 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                    ....


답변

당신은 쉽게 그렇게 할 수 없습니다.

그러한 장치를 제공하는 자체 커널 모듈을 작성하는 것을 고려할 수 있습니다. 나는 그것을 권장하지 않습니다.

일부 파이프 (또는 stdout) 또는 FIFO 에 동일한 바이트의 무한 스트림을 작성하는 작은 C 프로그램을 작성할 수 있습니다.

tr (1) 을 사용하여 /dev/zero0 바이트마다 읽고 다른 것으로 변환 할 수 있습니다.

적어도 줄 바꿈을 줄 여유가 있다면 (예를 들어 파이프에 tr -d '\n'…) 아마도 yes (1) 사용할 수 있습니다


답변

당신이 경우에 그래서, 말 그대로 이 달성하고자하는, 당신은 사용할 수 있습니다 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 '동안 :; echo -n "\ 1"; 완료 '| pv -a> / dev / null
[225KiB / s]

$ bash -c '동안 :; 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]


답변

비트 마스크 / xor 0 바이트를 시도하고 무의미합니다. 그렇지 않습니까? 바이트 xor를 가져 와서 0으로 묶는 것은 아무 문제가 없습니다.

원하는 바이트를 제공하는 루프를 만들어 파이프 또는 명명 된 파이프 뒤에 놓습니다. 캐릭터 디바이스와 거의 동일하게 동작합니다 (유휴 상태 일 때 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)


답변

0을 읽고 각 0을 패턴으로 변환하십시오!

우리는에서 0 바이트를 읽고 각 0 바이트를 변환하여 각 바이트에 비트 마스크를 적용하는 데 /dev/zero사용 tr합니다.

$ </dev/zero tr '\000' '\176' | head -c 10
~~~~~~~~~~$

8 진수 176은의 ASCII 코드 ~이므로 10을 얻습니다 ~. ( $출력의 끝에는 쉘에 줄 끝이 없음을 나타냅니다-다르게 보일 수 있습니다)

0xFF바이트를 만들어 봅시다 : Hex 0xFFis octal 0377. tr명령 행 에는 선행 0이 생략됩니다 . 마지막에, hexdump출력을 읽을 수있게 만드는 데 사용됩니다.

$ </dev/zero tr '\000' '\377' | head -c 10 | hexdump
0000000 ffff ffff ffff ffff ffff
000000a

여기에서는 16 진수 대신 문자의 8 진수 코드를 사용해야합니다. 따라서 \0008 에서 8 까지의 범위입니다 \377(와 동일 0xFF). 및 을
사용 하여 16 진수 또는 8 진수 색인 번호가있는 문자 표를 가져옵니다.
(10 진수와 16 진수가있는 테이블의 경우 그냥 ).ascii -xascii -o
ascii

꽤 빠른

0을 사용하는 것에 비해 상당히 빠릅니다. cat /dev/zeroIO 버퍼링을 완벽하게 사용할 수는 있지만 4 배나 빠릅니다 tr.

$ </dev/zero tr '\000' '\176' | pv -a >/dev/null
[ 913MB/s]

$ </dev/zero cat | pv -a >/dev/null
[4.37GB/s]


답변

데이터로 수행하려는 작업과 사용하려는 유연성에 따라 다릅니다.

속도가 필요한 최악의 경우 / dev / zero와 동일하게 수행하고 장치에서 / dev / one, / dev / two, .. / dev / fourtytwo .. 등을 컴파일하면됩니다.

대부분의 경우 필요한 위치에 직접 데이터를 작성하는 것이 좋습니다. 따라서 프로그램 / 스크립트 내에서 상수입니다. 정보가 많을수록 사람들이 더 잘 도울 수 있습니다.