비트 마스크를 어떻게 설정 /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 ...)
두 번째 줄 을 쓰려고 했습니까 ?
-v
직접 직후라는 이름의 변수를 설정하려면 발발했습니다 출력을 발생합니다; 이 경우 변수 이름은 o
( octal )- -v
옵션은 쉘 내장 버전 printf
( / usr / bin / printf 버전이 아님)에 적용됩니다.
-v
옵션은 변수가 지정한 값으로 정확하게 설정되도록 합니다. $(...)
먼저 출력을 변환합니다. 그렇기 때문에 o=$(printf '\n')
당신이 기대할 수있는 효과가 없을 것 printf -vo '\n'
입니다. (여기서 출력은 그러한 변환에 영향을받지 않는 형태이기 때문에 여기서는 중요하지 않지만 -v
옵션을 모르면 알면 도움이 될 것입니다.)
당신은 쉽게 그렇게 할 수 없습니다.
그러한 장치를 제공하는 자체 커널 모듈을 작성하는 것을 고려할 수 있습니다. 나는 그것을 권장하지 않습니다.
일부 파이프 (또는 stdout
) 또는 FIFO 에 동일한 바이트의 무한 스트림을 작성하는 작은 C 프로그램을 작성할 수 있습니다.
tr (1) 을 사용하여 /dev/zero
0 바이트마다 읽고 다른 것으로 변환 할 수 있습니다.
적어도 줄 바꿈을 줄 여유가 있다면 (예를 들어 파이프에 tr -d '\n'
...) 아마도 yes (1) 사용할 수 있습니다
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 '동안 :; 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]
perl
2.13GiB, 8.73GiB를 < /dev/zero
산출합니다. 어떤 것이 성능에 영향을 줄 수 있습니까?
perl
다른 솔루션보다 지속적으로 빠릅니다. 컴파일 된 C 프로그램과 동일한 처리량을 얻습니다. 벤치 마크는 여기에서 시스템 스케줄러와 마찬가지로 응용 프로그램에 관한 것입니다. 가장 다른 점은 기록되는 버퍼의 크기입니다.
cat /dev/zero| pv -a >/dev/null
당신에게 초당 약 2GiB를 줄 것이라고 생각한다 < /dev/zero
.
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 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
)
argc == 1+1
대신에 agrc == 2
?
0 XOR X == X
.
우리는에서 0 바이트를 읽고 각 0 바이트를 변환하여 각 바이트에 비트 마스크를 적용하는 데 /dev/zero
사용 tr
합니다.
$ </dev/zero tr '\000' '\176' | head -c 10
~~~~~~~~~~$
8 진수 176은의 ASCII 코드 ~
이므로 10을 얻습니다 ~
. ( $
출력의 끝에는 쉘에 줄 끝이 없음을 나타냅니다-다르게 보일 수 있습니다)
0xFF
바이트를 만들어 봅시다 : Hex 0xFF
is octal 0377
. tr
명령 행 에는 선행 0이 생략됩니다 . 마지막에, hexdump
출력을 읽을 수있게 만드는 데 사용됩니다.
$ </dev/zero tr '\000' '\377' | head -c 10 | hexdump
0000000 ffff ffff ffff ffff ffff
000000a
여기에서는 16 진수 대신 문자의 8 진수 코드를 사용해야합니다. 따라서 \000
8 에서 8 까지의 범위입니다 \377
(와 동일 0xFF
). 및 을
사용 하여 16 진수 또는 8 진수 색인 번호가있는 문자 표를 가져옵니다.
(10 진수와 16 진수가있는 테이블의 경우 그냥 ).ascii -x
ascii -o
ascii
0을 사용하는 것에 비해 상당히 빠릅니다. cat /dev/zero
IO 버퍼링을 완벽하게 사용할 수는 있지만 4 배나 빠릅니다 tr
.
$ </dev/zero tr '\000' '\176' | pv -a >/dev/null
[ 913MB/s]
$ </dev/zero cat | pv -a >/dev/null
[4.37GB/s]