मैं / देव / शून्य पर थोड़ा सा मुखौटा कैसे लगा सकता हूं ताकि मुझे शून्य के अलावा बाइट मिल सके?


20

मैं थोड़ा सा मुखौटा कैसे लगा सकता हूं /dev/zeroताकि मेरे पास न केवल 0x00 के लिए एक स्रोत हो सकता है, बल्कि 0x01 और 0xFF के बीच किसी भी बाइट के लिए भी हो सकता है?


8
तुमने क्यों पूछा? कृपया इसे प्रेरित करने के लिए प्रश्न को संपादित करें।
बेसिल स्टारीनेविच 11

1
आप इस उत्तर को संदर्भ के रूप में उपयोग कर सकते हैं: stackoverflow.com/questions/12634503/how-to-use-xor-in-bash
रोमियो निनोव

मैंने इस सवाल का जवाब दिया, लेकिन इसे पढ़कर मुझे लगता है कि मैंने इसे गलत समझा। क्या आप प्रत्येक 0x00को एक विशिष्ट मान या 0x00-0xFFश्रेणी में एक यादृच्छिक मूल्य पर अनुवाद करना चाहते हैं ?
कोस

1
@ एक विशिष्ट मान की तरह प्रत्येक 444444...एक यादृच्छिक एक नहीं
एडुआर्ड फ्लोरिंसक्यू

जवाबों:


18

निम्नलिखित bashकोड काम करने के लिए सेट बाइट के साथ में representred की जा रही है द्विआधारी । हालांकि आप आसानी से संभाल करने के लिए इसे बदल सकते हैं ocatal , दशमलव या हेक्स बस बदलकर मूलांक r का मूल्य 2 के लिए 8, 10या 16क्रमशः और स्थापित करने b=के हिसाब से।

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

EDIT - यह बाइट मानों की पूरी श्रृंखला को संभालता है : हेक्स 00 - एफएफ (जब मैंने नीचे 00-7 एफ लिखा था, तो मैं केवल एकल-बाइट यूटीएफ -8 वर्णों पर विचार कर रहा था)।

यदि, उदाहरण के लिए, आप केवल 4 बाइट्स चाहते हैं (UTF-8 'ASCII'- केवल हेक्स 00-7F रेंज में वर्ण) , तो आप इसे सिर में पाइप कर सकते हैं :... | head -c4

आउटपुट (4 वर्ण):

~~~~

8-बिट प्रारूप में आउटपुट देखने के लिए, इसे xxd(या किसी अन्य 1 और 0 बाइट डंप *) में पाइप करें :
उदा। b=10000000और पाइपिंग:... | head -c4 | xxd -b

0000000: 10000000 10000000 10000000 10000000                    ....

1
क्या आपको o=$(printf ...)दूसरी पंक्ति के लिए लिखने का मतलब था?
jwodder

1
@jwodder: नहीं, दूसरी पंक्ति सही है जैसा कि दिखाया गया है। Printf विकल्प -vtthe उत्पादन सीधे चर यह तुरंत बाद नामित सेट करने के लिए कारण बनता है, इस मामले में कि चर का नाम o( अष्टक के लिए ) है - ध्यान दें कि -vविकल्प शेल-बिल्टिन संस्करण पर लागू होता है printf(नहीं / usr / bin / printf संस्करण के लिए)
Peter.O

2
@jwodder इसके अलावा, सामान्य तौर पर, -vविकल्प यह सुनिश्चित करता है कि चर आपके द्वारा निर्दिष्ट किए गए वास्तव में सेट हो जाए । $(...)पहले आउटपुट को बदल देता है। यही कारण है कि o=$(printf '\n')प्रभाव नहीं होगा जो आप उम्मीद कर सकते हैं, जबकि printf -vo '\n'करता है। (इससे कोई फर्क नहीं पड़ता, क्योंकि यहाँ आउटपुट एक ऐसे रूप में है जो इस तरह के परिवर्तन से अप्रभावित है, लेकिन अगर आप -vविकल्प से अनजान थे , तो यह जानना उपयोगी हो सकता है।)
hvd

18

आप आसानी से ऐसा नहीं कर सकते।

आप इस तरह की डिवाइस प्रदान करने के लिए अपने स्वयं के कर्नेल मॉड्यूल को लिखने पर विचार कर सकते हैं। मैं यह सलाह नहीं देता।

आप कुछ पाइप (या पर stdout) या फीफो पर एक ही बाइट्स की अनंत धारा लिखने वाला एक छोटा सी प्रोग्राम लिख सकते हैं ।

आप प्रत्येक 0 बाइट को किसी और चीज़ से पढ़ने और अनुवाद करने के लिए tr (1) का उपयोग कर सकते हैं /dev/zero

आप शायद हाँ (1) का उपयोग कर सकते हैं, कम से कम यदि आप नए सिरे से कर सकते हैं (या फिर इसे पाइप में tr -d '\n'...)


10
या yes 1 | tr -d $'\n'उस बात के लिए उपयोग करें ।
कोजिरो

3
@kojiro: यदि आप वर्णों yesकी एक धारा के लिए प्रयास करते हैं तो विफल हो जाएगा \n। एक विकल्प जो संभालता \nहै: yes '' | tr '\n' "$c"- जहां $cएएससीआईआई वर्णों की पूरी श्रृंखला का कोई भी चार्ट हो सकता है।
पीटर।

1
@ पीटर। मुझे यकीन नहीं है कि आपने मेरी टिप्पणी की व्याख्या शाब्दिक, स्थिर अभिव्यक्ति के अलावा कुछ और कैसे की है yes 1 | tr -d $'\n'। मुझे लगता है कि आप एक शेल का उपयोग कर सकते हैं जो $''बैकस्लैश उपचार नहीं करता है , या आप एक लोकेल खोजने की कोशिश कर सकते हैं जो बदल जाता है tr -d $'\n', लेकिन मैंने अभी तक इसे नहीं पाया है।
कोजिरो

@ कोकोजी: आपका चरित्र yes 1 | tr -d $'\n'बहुत खुशी से 1पात्रों की एक धारा और लगभग हर दूसरे एकल-बाइट मूल्य को प्रिंट करेगा, लेकिन यह \nपात्रों की एक धारा नहीं छाप सकता है । ओपी सभी बाइट मूल्यों "0x01 और 0xFF के बीच"
पीटर।

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

13

ठीक है, अगर आप सचमुच इसे हासिल करना चाहते हैं , तो आप LD_PRELOAD हुक का उपयोग कर सकते हैं । मूल विचार सी लाइब्रेरी से किसी फ़ंक्शन को फिर से लिखना और सामान्य के बजाय इसका उपयोग करना है।

यहां एक सरल उदाहरण है जहां हम 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 / शून्य से जुड़ा हुआ है। उसके बाद, हम केवल 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 / शून्य, प्रतीक्षारत / dev / capbee और अकेले / dev / शून्य से प्रतीकात्मक लिंक हो सकता है। // dev / शून्य मधुमक्खी के समान / dev / शून्य नहीं होगा।
रॉबर्ट जैकब्स

1
@RobertJacobs वास्तव में। हम सिमिलिंक / देव / 0x01, / देव / 0x02, / देव / 0x03, ... / / देव / शून्य उत्पन्न कर सकते हैं और बिटनाम को लागू करने के लिए फ़ाइल नाम को पार्स कर सकते हैं।
योना

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]

$ डैश -c 'जबकि:; इको-एन "\ 1" करें; किया '| pv -a> / dev / null
[225KiB / s]
$ बैश -c 'जबकि:; प्रतिध्वनि करें "-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। क्या चीज प्रदर्शन को प्रभावित कर सकती है?
congonglm

@cuonglm, हां, मुझे सिस्टम के बीच कुछ भिन्नता दिखाई देती है, लेकिन perlअन्य समाधानों की तुलना में लगातार तेज है। मुझे समान संकलित C प्रोग्राम के साथ समान थ्रूपुट मिलता है। बेंचमार्क एप्लिकेशन पर उतना ही है जितना कि सिस्टम के शेड्यूलर पर। जो चीज़ सबसे अलग है वह बफ़र्स के आकार को लिखा जा रहा है।
स्टीफन चेज़लस

@cuonglm पाइप इसे धीमा कर देता है। मुझे लगता है कि cat /dev/zero| pv -a >/dev/nullआप प्रति सेकंड लगभग 2 GiB देंगे (यह मेरे सिस्टम पर करता है, जबकि < /dev/zero) मुझे लगभग 6GiBps देता है।
PSkocik

@ स्टीफनचैलेजेलस मैं पूछता हूं कि आप किस सिस्टम पर हैं, स्टीफन चेजेलस? मेरे परिणाम काफी भिन्न हैं (मैं पर्ल संस्करण से लगभग 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

1
@PSkocik, Linux 3.16.0-4-amd64 # 1 एसएमपी डेबियन 3.16.7-ckt9-3 (2015-04-23) x86_64 GNU / लिनक्स, इंटेल (R) कोर (TM) 2 डुओ सीपीयू T6600 @ 2.80GHz। नया कर्नेल एक अंतर बनाता है (जब तक कि यह नया पर्ल न हो: v5.20.2)
स्टीफन चेज़लस

7

यह कोशिश करने के लिए व्यर्थ है और बिटमास्क / एक्सआर शून्य बाइट्स है, है ना? एक बाइट लेना और xorइसे शून्य के साथ सम्मिलित करना एक नो-ऑप है।

बस एक लूप बनाएं जो आपको इच्छित बाइट्स देता है और इसे पाइप या नामित पाइप के पीछे रखता है। यह एक चरित्र उपकरण के रूप में बहुत ज्यादा व्यवहार करेगा (निष्क्रिय होने पर सीपीयू चक्र बर्बाद नहीं करेगा):

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 में पुचर का उपयोग करने की कोशिश की, लेकिन यह धीमा था।
PSkocik

जिज्ञासा से बाहर, argc == 1+1इसके बजाय क्यों agrc == 2?
मोनिका को पुनः स्थापित करें - notmaynard

@iamnotmaynard खुद को याद दिलाने के लिए कि यह कमांड लाइन के निष्पादन योग्य प्लस 1 तर्क के लिए 1 है। :-D
PSkocik

आह। यह मेरा अनुमान था, लेकिन यह सुनिश्चित करना चाहता था कि कुछ गुप्त कारण नहीं था।
मोनिका को बहाल करना - notmaynard

"एक बाइट लेना और शून्य के साथ इसे नो-ऑप करना है।" यह सच नहीं है 0 XOR X == X:।
जाकवह

5

शून्य पढ़ें, अपने पैटर्न में प्रत्येक शून्य का अनुवाद करें!

हम शून्य बाइट्स को पढ़ते हैं /dev/zero, और trप्रत्येक बाइट्स का अनुवाद करके प्रत्येक बाइट्स पर एक बिट मास्क लगाने के लिए उपयोग करते हैं :

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

ऑक्टल 176 एससीआई कोड है ~, इसलिए हमें 10 मिलते हैं ~। ( $आउटपुट के अंत में मेरे शेल में संकेत मिलता है कि कोई लाइन अंत नहीं था - यह आपके लिए अलग दिख सकता है)

तो, चलो 0xFFबाइट्स बनाते हैं : हेक्स 0xFFऑक्टल है 0377। अग्रणी शून्य को trकमांड लाइन के लिए छोड़ दिया जाता है ; अंत में, hexdumpआउटपुट को पठनीय बनाने के लिए उपयोग किया जाता है।

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

आपको यहां हेक्साडेसिमल के बजाय वर्णों के अष्टक कोड का उपयोग करने की आवश्यकता है। तो यह \000अष्टक \377(समान 0xFF) से लेकर तक है ।
का प्रयोग करें ascii -xऔर ascii -oहेक्साडेसिमल या अष्टाधारी सूचकांक के साथ पात्रों में से एक मेज पाने के लिए।
(दशमलव और हेक्साडेसिमल के साथ एक तालिका के लिए, बस ascii)।

जल्दी

यह काफी तेजी से चलता है, सिर्फ शून्य का उपयोग करने की तुलना में: cat /dev/zeroकेवल चार गुना तेज है, जबकि यह आईओ बफरिंग का सही उपयोग trकर सकता है , जो नहीं कर सकता।

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

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

3

निर्भर करता है कि आप डेटा के साथ क्या करना चाहते हैं और आप इसका उपयोग कितना लचीला चाहते हैं।

सबसे खराब स्थिति यदि आपको गति की आवश्यकता है, तो आप / dev / शून्य के समान ही कर सकते हैं, और / / dev / one, / dev / two, .. / dev / fourtytwo .. और इत्यादि उपकरणों को संकलित कर सकते हैं।

ज्यादातर मामलों में डेटा को सीधे उस जगह बनाना बेहतर होना चाहिए, जहां उसकी जरूरत है, इसलिए एक प्रोग्राम / स्क्रिप्ट के अंदर एक स्थिरांक के रूप में। अधिक जानकारी के साथ लोग आपकी बेहतर मदद कर सकते हैं।


1

Infinte प्रिंटफ लूप

\u00आप चाहते हैं बाइट के साथ Reeplace ।

while true ; do printf "\u00" ; done | yourapp

C ++ कोड:

#include<cstdio>

int main(){
 char out=Byte;
 while(true)
 fwrite(&out,sizeof(out),1,stdout);
}

संकलित करें:Byte आप चाहते हैं कि मूल्य के साथ reeplace ।

g++ -O3 -o bin file.cpp -D Byte=0x01

उपयोग

./bin | yourapp

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.