ฉันใช้คำสั่งต่อไปนี้ในระบบอูบุนตู:
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
จะsync
hronize บล็อกอ่านใน 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
ค่าสุ่ม "สุ่ม" น้อยกว่าหรือตรวจสอบพูลเอนโทรปีของคุณ (ในลูปและรอตามที่ต้องการ) ...