ฉันใช้คำสั่งต่อไปนี้ในระบบอูบุนตู:
dd if=/dev/random of=rand bs=1K count=2
อย่างไรก็ตามทุกครั้งที่รันฉันจะพบว่าไฟล์มีขนาดแตกต่างกัน ทำไมนี้ ฉันจะสร้างไฟล์ขนาดที่กำหนดซึ่งเต็มไปด้วยข้อมูลแบบสุ่มได้อย่างไร
iflag=fullblock
ฉันใช้คำสั่งต่อไปนี้ในระบบอูบุนตู:
dd if=/dev/random of=rand bs=1K count=2
อย่างไรก็ตามทุกครั้งที่รันฉันจะพบว่าไฟล์มีขนาดแตกต่างกัน ทำไมนี้ ฉันจะสร้างไฟล์ขนาดที่กำหนดซึ่งเต็มไปด้วยข้อมูลแบบสุ่มได้อย่างไร
iflag=fullblock
คำตอบ:
คุณสังเกตการรวมกันของพฤติกรรมที่แปลกประหลาดของที่มีพฤติกรรมที่แปลกประหลาดของลินุกซ์dd /dev/randomทั้งสองอย่างนั้นไม่ค่อยเป็นเครื่องมือที่เหมาะสมสำหรับงาน
Linux /dev/randomส่งคืนข้อมูลเท่าที่จำเป็น มันขึ้นอยู่กับข้อสันนิษฐานว่าเอนโทรปีของเครื่องกำเนิดหมายเลขเทียมถูกดับในอัตราที่รวดเร็วมาก เนื่องจากการรวบรวมเอนโทรปีใหม่นั้นช้า/dev/randomโดยทั่วไปจะปล่อยเพียงไม่กี่ไบต์ต่อครั้ง
ddเป็นโปรแกรมเก่าที่บ้าๆบอ ๆ ตั้งใจแรกเริ่มที่จะทำงานบนอุปกรณ์เทป เมื่อคุณบอกให้อ่านหนึ่งบล็อกของ 1kB มันจะพยายามอ่านหนึ่งบล็อก ถ้าการอ่านส่งกลับน้อยกว่า 1024 ไบต์ยากนั่นคือทั้งหมดที่คุณได้รับ ดังนั้นจึงโทรออกdd if=/dev/random bs=1K count=2สองread(2)สาย เนื่องจากเป็นการอ่านจากโดยทั่วไปการโทร/dev/randomทั้งสองreadจะกลับมาเพียงไม่กี่ไบต์ในจำนวนที่แตกต่างกันขึ้นอยู่กับเอนโทรปีที่มีอยู่ ดูเพิ่มเติมเมื่อใดเหมาะสำหรับการคัดลอกข้อมูล (หรือเมื่อมีการอ่าน () และเขียน () บางส่วน)
ถ้าคุณกำลังออกแบบการติดตั้ง OS หรือ Cloner คุณไม่ควรใช้/dev/randomภายใต้ Linux /dev/urandomเสมอ urandomหน้าคนค่อนข้างเข้าใจผิด; /dev/urandomในความเป็นจริงแล้วเหมาะสำหรับการเข้ารหัสแม้กระทั่งการสร้างคีย์ที่มีอายุการใช้งานยาวนาน ข้อ จำกัด เพียงอย่างเดียว/dev/urandomคือต้องให้เอนโทรปีเพียงพอ การแจกแจง Linux มักจะบันทึกเอนโทรปีระหว่างการรีบูตดังนั้นครั้งเดียวที่คุณอาจมีเอนโทรปีไม่เพียงพอที่อยู่ในการติดตั้งใหม่ เอนโทรปีไม่สวมในแง่ปฏิบัติ สำหรับข้อมูลเพิ่มเติมอ่านrand จาก / dev / urandom ปลอดภัยสำหรับรหัสเข้าสู่ระบบหรือไม่? และเอนโทรปีการให้อาหาร / dev / สุ่ม .
การใช้งานส่วนใหญ่ddจะแสดงได้ดีขึ้นด้วยเครื่องมือเช่นหรือhead tailหากคุณต้องการ 2kB ของการสุ่มไบต์ให้เรียกใช้
head -c 2k </dev/urandom >rand
ด้วยเคอร์เนล Linux ที่เก่ากว่าคุณสามารถหนีไปได้
dd if=/dev/urandom of=rand bs=1k count=2
เพราะ/dev/urandomมีความสุขกลับมาเป็นจำนวนมากตามที่ร้องขอ แต่นี้ไม่เป็นความจริงอีกต่อไปตั้งแต่เคอร์เนล 3.16, ก็ตอนนี้ จำกัด อยู่ที่ 32MB
โดยทั่วไปเมื่อคุณจำเป็นต้องใช้ddในการสกัดจำนวนคงที่ของไบต์และใส่มันไม่ได้มาจากไฟล์ปกติหรืออุปกรณ์ป้องกัน, dd bs=1 count=2048คุณจะต้องอ่านไบต์โดยไบต์:
/dev/urandom 32m read()
dd if=/dev/urandom ibs=1k obs=1k | dd bs=1k count=2
จากman 4 randomในกล่อง RHEL 5:
เมื่ออ่านอุปกรณ์ / dev / random จะส่งกลับสุ่ม bytes ภายในจำนวนบิตของสัญญาณรบกวนใน Entropy pool โดยประมาณ
ฉันได้ไฟล์ขนาด 213 ไบต์บนเครื่องนั้น กลับไปชาย 4 สุ่ม:
เมื่ออ่านแล้วอุปกรณ์ / dev / urandom จะกลับมาเป็นจำนวนมากตามที่ร้องขอ
ฉันได้รับ 2048 ไบต์จากการเรียกใช้ทุกครั้ง dd if=/dev/urandom of=rand bs=1K count=2
ฉันสรุปได้ว่าความแตกต่างนั้นเกิดจากเอนโทรปีที่เครื่องของคุณสร้างขึ้นระหว่างการขอร้อง dd if=/dev/random ...
dd if=/dev/random bs=1K count=2หยุดเมื่อเห็นได้ชัดว่าเอนโทรปีของการระบายน้ำ จากเอกสารมันควรบล็อกจนกว่าจะมีเอนโทรปีมากขึ้นดังนั้นมันddจะเขียนไฟล์ออกอย่างช้าๆแทนที่จะปล่อยทิ้งพูลปัจจุบันและออกไป
read(fd, mybuf, 1024)FD ที่ปิดกั้นมันจะกลับมาทันทีที่อุปกรณ์อ้างอิงส่งคืนข้อมูลบางส่วน หากมี 1024 ไบต์ที่ต้องอ่านจะส่งคืนค่านั้น หากมีเพียง 201 ไบต์ก็จะส่งคืน 201 หากมี 0 ไบต์ก็จะบล็อกจนกว่าจะมีอย่างน้อยหนึ่งไบต์จะใช้งานได้แล้วส่งคืน / พวกเขา
ทำไมddข้อมูลหล่น ... Gillesได้โพสต์คำถามที่น่าสนใจเกี่ยวกับdd:
dd เหมาะสำหรับการคัดลอกข้อมูลเมื่อใด (หรือเมื่อมีการอ่าน () และเขียน () บางส่วน)
นี่คือข้อความที่ตัดตอนมาจากคำถามนั้น:
* ... มันไม่ใช่เรื่องยากที่จะใส่ dd ผิด ตัวอย่างเช่นลองใช้รหัสนี้: **
yes | dd of=out bs=1024k count=10
และตรวจสอบขนาดของไฟล์ (อาจมีขนาดต่ำกว่า 10MB)
นอกเหนือจากความคิดเห็นของฉัน (ในตอนท้ายของคำถามของคุณ) บางอย่างเช่นนี้เป็น iteresting จะดู ... $trndมันจับไบต์ในไฟล์ ฉันเลือก bs = 8 โดยพลการ
เลื่อนเมาส์ของคุณและดูมันเร็วขึ้น
เมื่อคอมพิวเตอร์ของฉันไม่มีการใช้งาน (AFK และไม่มีกิจกรรมเครือข่าย) และหลังจากหมดเอนโทรปีพูมันใช้เวลา2 ชั่วโมง 12 นาทีในการเก็บรวบรวมเพียง1,222ไบต์ที่จุดนี้ฉันยกเลิก
จากนั้นเมื่อฉันขยับเมาส์อย่างต่อเนื่องฉันใช้เวลาสั้นลง1 นาที 15 วินาทีในการรวบรวมจำนวนไบต์เท่ากัน
นี้แสดงให้เห็นอย่างชัดเจนว่าสวยเก็บรวบรวมเอนโทรปีไม่ได้ตามความเร็วของ CPU แต่มันเป็นเหตุการณ์สุ่มตามและที่ Ubuntu ระบบของฉันใช้เมาส์เป็นหนึ่งในตัวของมันอย่างมีนัยสำคัญปัจจัยสุ่ม
get=2048
trnd=/tmp/$USER.rnd; >"$trnd"
while (( $(wc -c <"$trnd") < $get )) ;do
dd if=/dev/random bs=8 count=1 2>/dev/null >>"$trnd"
echo -n "itt: $((i+=1)) ct: "; wc -c <"$trnd"
done
truncate -s $get "$trnd"
echo -e "\nfinal count: "; wc -c <"$trnd"
ddถูกออกแบบมาสำหรับการปิดกั้น - ก็มักจะเป็นเครื่องมือที่ดีที่สุดในการกำจัดของคุณสำหรับการอ่านจากปัจจัยการผลิตขนาดตัวแปรถ้าคุณต้องการมันทำทันทีเพราะddจะไม่ buffer ปัจจุบันอ่านในอนาคตบางwrite() (เว้นแต่คุณมากอย่างชัดเจนกำหนดค่ามันเป็นอย่างนั้นกับ OBS ขนาดใหญ่กว่า IBS)แต่จะแทนwrite()ทุกอย่างมันอ่านเร็วที่สุดเท่าที่มันread()ล่ะ(และเลือกที่จะประมวลผล)
นี่คือคำจำกัดความสำคัญ:
ibs=expr
expr obs=expr
expr bs=expr
exprไบต์แทนและibs= obs=หากไม่มีการแปลงนอกเหนือจากsync, noerrorและnotruncระบุไว้แต่ละบล็อคอินพุตจะถูกคัดลอกไปยังเอาต์พุตเป็นบล็อกเดียวโดยไม่มีการรวมบล็อกสั้น ๆดังนั้นคุณจะเห็นเมื่อibsและobsจะมีการกำหนดร่วมกันเป็นbsแล้วibsจะมีความสำคัญ - แต่อย่างอื่นถ้าคุณมีความเฉพาะเจาะจงแล้วทั้งobsหรือcbsไม่
นี่คือตัวอย่างที่ibsสำคัญที่สุด คุณอาจทำอะไรแบบนี้ถ้าคุณต้องการติดตามว่า/dev/randomสระว่ายน้ำเต็มไปเร็วแค่ไหน...
dd "ibs=$size" conv=sync "count=$lmt" \
if=/dev/random of="$somefile"
ตราบใดที่if='s เป้าหมายสามารถอ่านได้ที่ทุกคนที่จะเสมอส่งผลให้การส่งออกไฟล์ขนาดเดียวกันเพราะddจะsynchronize บล็อกอ่านใน nulls กล่าวอีกนัยหนึ่งคือถ้าdd read()s สำหรับอินพุตบล็อกของ$((size=10)) $((count=5))เวลาและread()ไฟล์ส่งคืน 2 ไบต์จากนั้น 8 ไบต์จากนั้น 12 ไบต์จากนั้น 12 ไบต์จากนั้น 2 ไบต์จากนั้น 4 ไบต์ddจะเขียนลงในไฟล์ outfile เช่น
2 read bytes 8NULs \
8 read bytes 2NULs \
10 read bytes 0NULs \
4 read bytes 6NULs \
4 read bytes 6NULs
... เพราะddโดยค่าเริ่มต้นจะไม่ล่าช้า ดังนั้นหากคุณต้องการติดตามอินสตรีมและกำหนดขอบเขตการเขียนของกระบวนการอื่นddเป็นเครื่องมือสำหรับคุณ
หากคุณเพิ่งเขียนข้อมูลจำนวนหนึ่งไปยังไฟล์ปกติตรงกันข้ามกับข้อความอื่น ๆ ที่เกิดขึ้นที่นี่คุณสามารถใช้ddสิ่งนี้ - และค่อนข้างง่าย - แต่คุณต้องมีมากกว่าหนึ่งตัวและปัจจัยการบล็อกที่เชื่อถือได้
ตัวอย่างเช่นถ้าคุณทำ:
{ dd ibs="$size" obs="${size}x$block_factor" |
dd bs="${size}x$blockfactor" "count=$lmt"
} <infile >outfile
... คนแรกที่ddจะ buffer เป็นจำนวนมากibs="$size"บล็อกการป้อนข้อมูลที่เป็นความจำเป็นในการกรอกข้อมูลอย่างน้อยหนึ่งobs="${size}x$block_factor"บล็อกเอาท์พุทสำหรับทุกท่อระหว่างมันและสองwrite() ddซึ่งหมายความว่ารายการที่สองddสามารถ จำกัด ผลลัพธ์ได้อย่างน่าเชื่อถือcount="$lmt"เพราะสิ่งที่write()ทำครั้งแรกทั้งหมดจะจับคู่กับขนาดบล็อกของ i / o โดยไม่คำนึงว่าจะต้องทำread()ครั้งแรกกี่ครั้งdd
และนั่นคือวิธีที่คุณสามารถใช้ddเพื่ออ่านไพพ์หรือไฟล์พิเศษชนิดอื่น ๆ ได้อย่างน่าเชื่อถือ - ด้วยคณิตศาสตร์เพียงเล็กน้อย
/dev/randomจะบล็อกหากมีจำนวนเอนโทรปีไม่เพียงพอที่จะสร้างจำนวนหลักที่คุณต้องการ มันใช้เวลานานในการรวบรวมจำนวนที่สุ่ม "สุ่ม" ที่มีคุณภาพสูงของ psuedo ... ใช้ทั้ง/dev/urandomค่าสุ่ม "สุ่ม" น้อยกว่าหรือตรวจสอบพูลเอนโทรปีของคุณ (ในลูปและรอตามที่ต้องการ) ...