আমি কীভাবে / দেব / শূন্যে কিছুটা মাস্ক লাগাতে পারি যাতে আমি শূন্য ব্যতীত অন্য কোনও বাইট পেতে পারি?


20

আমি কীভাবে একটি বিট মাস্ক লাগাতে পারি /dev/zeroযাতে আমার কেবল 0x00 নয় তবে 0x01 এবং 0xFF এর মধ্যে কোনও বাইটের জন্য উত্স থাকতে পারে?


8
কেন জিজ্ঞাসা করছ? এটি উত্সাহিত করতে দয়া করে প্রশ্নটি সম্পাদনা করুন।
বেসিল স্টারিঙ্কেভিচ

1
: আপনি রেফারেন্স হিসেবে এই উত্তরটি ব্যবহার করতে পারেন stackoverflow.com/questions/12634503/how-to-use-xor-in-bash
রোমিও Ninov

আমি এই প্রশ্নের উত্তর দিয়েছি, কিন্তু এটি আবার পড়তে আমার মনে হয় আমি এটি ভুল বুঝেছি। আপনি কি প্রত্যেককে 0x00একটি নির্দিষ্ট মান বা 0x00-0xFFসীমার কোনও এলোমেলো মানের অনুবাদ করতে চান ?
কোস

1
@ এটিকে প্রতিটি 444444...এলোমেলো নয় এমন একটি নির্দিষ্ট মান হিসাবে দেখান
এডুয়ার্ড ফ্লোরিয়েন্সকু

উত্তর:


18

নিম্নলিখিত bashকোডটি বাইনারিতে প্রতিনিধিত্ব করা বাইটের সাথে কাজ করতে সেট করা আছে । তবে আপনি সহজেই হ্যান্ডেল করতে তা পরিবর্তন করতে পারেন ocatal , দশমিক বা হেক্স কেবল পরিবর্তন করে র্যাডিক্স r মান 2 থেকে 8, 10বা16 যথাক্রমে এবং সেটিং b=অনুসারে।

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

সম্পাদনা - এটি বাইট মানগুলির পুরো পরিসীমা পরিচালনা করে : হেক্স 00 - এফএফ (যখন আমি নীচে 00-7F লিখেছিলাম, আমি কেবলমাত্র একক-বাইট ইউটিএফ -8 অক্ষর বিবেচনা করছি)।

উদাহরণস্বরূপ, যদি আপনি কেবল 4 বাইট চান (ইউটিএফ -8 'এএসসিআইআই'-কেবলমাত্র হেক্স 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
@ জাওড্ডার: না, দ্বিতীয় লাইনটি দেখানো মতই সঠিক। Printf, বিকল্প -vtthe আউটপুট সরাসরি পরিবর্তনশীল এটা পরে অবিলম্বে নামে সেট করতে হয়; এক্ষেত্রে ভেরিয়েবলের নাম o( অষ্টালের জন্য ) - নোট করুন যে -vবিকল্পটি শেল-বিল্টিন সংস্করণে printf( / usr / বিন /
প্রিন্টফ

2
@jwodder এছাড়াও, সাধারণভাবে, -vবিকল্পটি নিশ্চিত করে যে আপনার পরিবর্তনশীলটি ঠিক তেমনটি সেট হয়েছে । $(...)প্রথমে আউটপুট পরিবর্তন করে। যে কারণে o=$(printf '\n')আপনি আশা করতে পারেন এমন প্রভাব পড়বে না, যেখানে রয়েছে printf -vo '\n'। (এখানে কোনও ব্যাপার নেই, যেহেতু এখানে আউটপুটটি এমন রূপে রয়েছে যা এই জাতীয় রূপান্তর দ্বারা প্রভাবিত হয় না, তবে আপনি যদি -vবিকল্পটি সম্পর্কে অবগত না হন , তবে এটি জানার জন্য কার্যকর হতে পারে))
এইচডিভি

18

আপনি সহজেই এটি করতে পারবেন না।

আপনি এই জাতীয় ডিভাইস সরবরাহ করে আপনার নিজের কার্নেল মডিউলটি লিখতে বিবেচনা করতে পারেন। আমি যে সুপারিশ না।

আপনি কিছু পাইপতে (বা চালু) একই বাইটের অসীম স্ট্রিম লিখে একটি ক্ষুদ্র সি প্রোগ্রাম লিখতে পারেন stdout ) বা ফিফোতে ।

আপনি ব্যবহার করতে পারে TR (1) থেকে পড়তে/dev/zero এবং প্রতি 0 বাইট অন্য কিছুতে অনুবাদ ।

আপনি সম্ভবত হ্যাঁ (1) ব্যবহার করতে পারেন , কমপক্ষে আপনি যদি নতুন লাইনের সাথে সামর্থ রাখতে পারেন (বা অন্যথায় এটি পাইপ করুন tr -d '\n'...)


10
বা yes 1 | tr -d $'\n'এই বিষয়ে ব্যবহার করুন ।
কোজিরো

3
@ কোজিরো: যদি আপনি চরিত্রের yesস্রোতে চেষ্টা করেন তবে তা ব্যর্থ হবে \n। একটি বিকল্প যা হ্যান্ডল করে \nতা হ'ল: yes '' | tr '\n' "$c"- যেখানে $cASCII অক্ষরের পূর্ণ পরিসরের যে কোনও চর হতে পারে।
পিটার.ও

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;
পিএসকোকিক

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 / শূন্যের সাথে সম্পর্কিত ফাইল বর্ণনাকারী আনতে। তারপরে, আমরা কেবল আমাদের পড়ার () ফাংশনটিতে এক্সওআর সঞ্চালন করি যদি 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 / ক্যাপবি থেকে / দেব / শূন্যে একটি প্রতীকী লিঙ্ক রাখতে পারেন / ডিভ / ক্যাপবি অনুসন্ধান করতে এবং একা রেখে / দেব / শূন্যে থাকতে পারেন। // ডেভ / শূন্য / দেব / শূন্যের মতো হবে না।
রবার্ট জ্যাকবস

1
পছন্দ করেছেন আমরা বিটমাস্কটি প্রয়োগ করতে নির্ধারিত করতে / ডিভ / 0x01, / dev / 0x02, / dev / 0x03, ... থেকে / dev / 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]

$ ড্যাশ-সি 'যখন:; ইকো-এন "\ 1" করুন; সম্পন্ন '| pv -a> / dev / নাল
[225 কেবি / গুলি]
$ বাশ-সি 'সময়:; ইকো-এন "\ 1" করুন; সম্পন্ন '| pv -a> / dev / নাল
[180KiB / গুলি]

$ < /dev/zero pv -a > /dev/null
[5.56GiB/s]
$ cat /dev/zero | pv -a > /dev/null
[2.82GiB/s]

আমার ডেবিয়ানে, perl2.13GiB উত্পাদন করুন, যখন < /dev/zero8.73GiB ফলন করুন। কোন জিনিস কর্মক্ষমতা প্রভাবিত করতে পারে?
কিউংলম

@ কুওগলম, হ্যাঁ, আমি সিস্টেমের মধ্যে কিছু পার্থক্য দেখতে পাচ্ছি, তবে perlঅন্যান্য সমাধানের তুলনায় ধারাবাহিকভাবে দ্রুত। সমতুল্য সংকলিত সি প্রোগ্রামের সাথে একই থ্রুপুট পাই। এখানে সিস্টেমের শিডিয়ুলারের মতো আবেদনের উপরে বেঞ্চমার্কটি রয়েছে। যা সবচেয়ে বেশি আলাদা করে তোলে তা হল বাফারগুলির আকার লেখা।
স্টাফেন চ্যাজেলাস

@ কুওগলম পাইপটি এটিও কমিয়ে দেয়। আমি মনে করি cat /dev/zero| pv -a >/dev/nullআপনাকে প্রতি সেকেন্ডে প্রায় 2 গিগাবাইট দেবে (এটি আমার সিস্টেমে থাকে, যখন < /dev/zero) আমাকে প্রায় 6GiBps দেয়।
পিএসকোকিক

@ স্টাফেনচাজেলাস আমি জিজ্ঞাসা করতে পারি আপনি কী সিস্টেমে আছেন, স্টাফেন চাজেলাস? খনিতে ফলাফলগুলি বেশ আলাদা (আমি পার্ল সংস্করণ থেকে প্রায় 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ভিতরে ইন্টেল আই 5 কোর এ আছি ।
পিএসকোকিক

1
@ স্পস্কিক, লিনাক্স 3.16.0-4-amd64 # 1 এসএমপি দেবিয়ান 3.16.7-সিকিটি 9-3 (2015-04-23) x86_64 জিএনইউ / লিনাক্স, ইন্টেল (আর) কোর (টিএম) 2 ডুয়ো সিপিইউ টি 9600 @ 2.80GHz। নতুন কার্নেলটি কোনও পার্থক্য মনে হচ্ছে (এটি যতক্ষণ না নতুন পার্ল: v5.20.2)
স্টাফেন চেজেলাস

7

এটি বিটমাস্ক / এক্সওর শূন্য বাইট চেষ্টা করা অর্থহীন, তাই না? একটি বাইট নেওয়া এবং xorএটি শূন্যের সাথে নিযুক্ত করা কোনও অপশন নয়।

কেবলমাত্র একটি লুপ তৈরি করুন যা আপনাকে যে বাইটগুলি দেয় তা দেয় এবং এটি একটি পাইপ বা নামযুক্ত পাইপের পিছনে রাখে। এটি চরিত্রের ডিভাইসের মতোই বেশ ব্যবহার করবে (নিষ্ক্রিয় অবস্থায় সিপিইউ চক্র নষ্ট করবে না):

mkfifo pipe
while : ; do echo -n "a"; done > pipe &

এবং যদি আপনি এটিকে অতি-অনুকূল করতে চান তবে আপনি নীচের সি কোডটি ব্যবহার করতে পারেন:

#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.1 গিগাবাইট / এস (এর চেয়ে কিছুটা দ্রুত cat /dev/zero | pv -a >/dev/null)


আমি মূলত সিতে পুটচর ব্যবহার করার চেষ্টা করেছি, তবে এটি ধীর ছিল।
পিএসকোকিক

আউট কৌতুহল, কেন argc == 1+1পরিবর্তে agrc == 2?
মনিকা পুনরায় ইনস্টল করুন - নোটমায়ার্ড

@ iamnotmaynard নিজেকে স্মরণ করিয়ে দেওয়ার জন্য যে এটি কমান্ড লাইনের এক্সিকিউটেবল প্লাস 1 টি আর্গুমেন্টের জন্য 1। :-D
পিএসকোকিক

আহ। এটি আমার অনুমান, তবে কোনও গোপন কারণ নেই তা নিশ্চিত করতে চেয়েছিলেন।
মনিকা পুনরায় ইনস্টল করুন - নোটমায়ার্ড

"একটি বাইট নেওয়া এবং এটি শূন্যের সাথে জোর করা একটি অনাপট নয়।" এটি সত্য নয়: 0 XOR X == X
জ্যাকওয়াহ

5

জিরো পড়ুন, আপনার শৈলীতে প্রতিটি শূন্য অনুবাদ করুন!

আমরা বাইরে শূন্য বাইট পড়েছি /dev/zeroএবং trপ্রতিটি শূন্য বাইট অনুবাদ করে প্রতিটি বাইটে কিছুটা মাস্ক প্রয়োগ করতে ব্যবহার করি :

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

অক্টাল 176 হ'ল আসকি কোড ~, সুতরাং আমরা 10 পাই ~। ( $আউটপুট শেষে আমার শেলের মধ্যে ইঙ্গিত দেয় যে কোনও লাইনের শেষ ছিল না - এটি আপনার পক্ষে আলাদা দেখাচ্ছে)

সুতরাং, আসুন 0xFFবাইটগুলি তৈরি করুন : হেক্সটি 0xFFঅক্টাল 0377trকমান্ড লাইনের জন্য নেতৃস্থানীয় শূন্যটি বাকি আছে ; শেষে, hexdumpআউটপুটটিকে পঠনযোগ্য করে তোলার জন্য ব্যবহৃত হয়।

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

আপনাকে হেক্সাডেসিমালের পরিবর্তে অক্ষরের অষ্টাল কোডগুলি ব্যবহার করতে হবে। সুতরাং এটি \000অষ্টাল থেকে \377একই (একই 0xFF) to হেক্সাডেসিমাল বা অষ্টাল সূচক সংখ্যার সাথে অক্ষরগুলির একটি সারণীটি
ব্যবহার করুন 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

ইনফিন্ট প্রিন্টফ লুপ

\u00আপনি যে বাইটটি চান তা প্রতিস্থাপন করুন ।

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

সি ++ কোড:

#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.