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


20

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


8
왜 물어? 동기를 부여하기 위해 질문을 편집하십시오.
Basile Starynkevitch 2016 년

1
이 답변을 참조로 사용할 수 있습니다 : stackoverflow.com/questions/12634503/how-to-use-xor-in-bash
Romeo Ninov

이 질문에 대한 답변을했지만 다시 읽으면 이해하지 못하는 것 같습니다. 각 0x00값을 특정 값 또는 0x00-0xFF범위 의 임의 값 으로 변환 하시겠습니까?
kos

1
@kos 444444...는 임의의 값이 아닌 특정 값으로 각각
Eduard Florinescu

답변:


18

다음 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                    ....

1
o=$(printf ...)두 번째 줄 을 쓰려고 했습니까 ?
jwodder 2016 년

1
@jwodder : 아니요, 두 번째 줄은 그림과 같이 정확합니다. 의 printf 옵션은 -v직접 직후라는 이름의 변수를 설정하려면 발발했습니다 출력을 발생합니다; 이 경우 변수 이름은 o( octal )- -v옵션은 쉘 내장 버전 printf( / usr / bin / printf 버전이 아님)에 적용됩니다.
Peter.O

2
@jwodder 또한, 일반적으로이 -v옵션은 변수가 지정한 값으로 정확하게 설정되도록 합니다. $(...)먼저 출력을 변환합니다. 그렇기 때문에 o=$(printf '\n')당신이 기대할 수있는 효과가 없을 것 printf -vo '\n'입니다. (여기서 출력은 그러한 변환에 영향을받지 않는 형태이기 때문에 여기서는 중요하지 않지만 -v옵션을 모르면 알면 도움이 될 것입니다.)
hvd

18

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

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

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

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

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


10
또는 yes 1 | tr -d $'\n'그 문제에 사용하십시오.
kojiro 2016 년

3
@ kojiro : 문자 yes스트림을 시도하면 실패합니다 \n. 처리 할 수 있는 대안 \n은 다음과 같습니다. yes '' | tr '\n' "$c"$cASCII 문자의 전체 범위의 모든 문자가 될 수 있습니다.
Peter.O

1
@ Peter.O 리터럴 정적 표현식 이외의 것을 의미하기 위해 내 의견을 어떻게 해석했는지 잘 모르겠습니다 yes 1 | tr -d $'\n'. $''백 슬래시 처리를 수행하지 않는 쉘을 사용 하거나을 변경하는 로케일을 찾으려고 시도 tr -d $'\n'했지만 아직 찾지 못했습니다.
kojiro 2016 년

@ kojiro : 문자 yes 1 | tr -d $'\n'스트림 1과 거의 모든 단일 바이트 값을 행복하게 인쇄 하지만 \n문자 스트림을 인쇄 할 수는 없습니다 . OP는 "0x01과 0xFF 사이"의
Peter.O

1
loop() { if [ "$1" = $'\n' ]; then yes "$1"; else yes "$1" | tr -d $'\n' ; fi;
PSkocik 2016 년

13

당신이 경우에 그래서, 말 그대로 이 달성하고자하는, 당신은 사용할 수 있습니다 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

3
구현이 주어지면 / dev / capbee에서 / dev / zero 로의 심볼릭 링크를 가질 수 있고 / dev / capbee를 검색하고 / dev / zero 만 남겨 둘 수 있습니다. // dev / zero는 / dev / zero와 같지 않습니다.
Robert Jacobs

1
@RobertJacobs 실제로. / dev / 0x01, / dev / 0x02, / dev / 0x03 등의 심볼릭 링크를 / dev / zero에 생성하고 파일 이름을 구문 분석하여 적용 할 비트 마스크를 결정할 수도 있습니다.
yoann

11

속도면에서 내가 찾은 가장 빠른 것은 다음과 같습니다.

$ 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]

내 데비안에서는 perl2.13GiB, 8.73GiB를 < /dev/zero산출합니다. 어떤 것이 성능에 영향을 줄 수 있습니까?
cuonglm

@ cuonglm, 예, 시스템간에 약간의 변화가 있지만 perl다른 솔루션보다 지속적으로 빠릅니다. 컴파일 된 C 프로그램과 동일한 처리량을 얻습니다. 벤치 마크는 여기에서 시스템 스케줄러와 마찬가지로 응용 프로그램에 관한 것입니다. 가장 다른 점은 기록되는 버퍼의 크기입니다.
Stéphane Chazelas

@cuonglm 파이프도 느려집니다. 나는 cat /dev/zero| pv -a >/dev/null당신에게 초당 약 2GiB를 줄 것이라고 생각한다 < /dev/zero.
PSkocik 2016 년

@ StéphaneChazelas 어떤 시스템을 사용하고 있는지 물어볼 수 있습니까, Stéphane Chazelas? 내 결과는 상당히 다릅니다 (펄 버전에서 약 2.1GiB를 얻을 수 있습니다). 나는에있어 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 코어의 내부.
PSkocik 2016 년

1
@PSkocik, Linux 3.16.0-4-amd64 # 1 SMP 데비안 3.16.7-ckt9-3 (2015-04-23) x86_64 GNU / Linux, Intel® Core (TM) 2 Duo CPU T9600 @ 2.80GHz. : 새로운 커널은 (v5.20.2는 새로운 펄 않는 한) 변화를 가져올 것으로 보인다
스테판 Chazelas가를

7

비트 마스크 / 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)


원래 C에서 putchar를 사용해 보았지만 느 렸습니다.
PSkocik 2016 년

호기심에서, 왜 argc == 1+1대신에 agrc == 2?
Monica Monica 복원 – notmaynard

@iamnotmaynard 명령 행 실행 파일에 1을 더하고 인수가 1이라는 것을 상기시킨다. :-D
PSkocik 2016 년

아 그건 내 추측이지만 비밀 이유가 없는지 확인하고 싶었습니다.
Monica Monica 복원 – notmaynard

"바이트를 가져와 0으로 조정하는 것은 아무 문제가 없습니다." 사실이 아닙니다 : 0 XOR X == X.
jacwah

5

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]

3

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

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

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


1

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.