dd กำลังสร้างไฟล์สุ่ม 32 MB แทน 1 GB


50

ฉันต้องการสร้างไฟล์สุ่มขนาด 1 GB ดังนั้นฉันจึงใช้คำสั่งต่อไปนี้

dd if=/dev/urandom of=output bs=1G count=1

แต่ทุกครั้งที่ฉันเรียกใช้คำสั่งนี้ฉันจะได้รับไฟล์ขนาด 32 MB:

<11:58:40>$ dd if=/dev/urandom of=output bs=1G count=1
0+1 records in
0+1 records out
33554431 bytes (34 MB, 32 MiB) copied, 0,288321 s, 116 MB/s

เกิดอะไรขึ้น?

แก้ไข:

ขอบคุณคำตอบที่ยอดเยี่ยมในหัวข้อนี้ฉันมาพร้อมกับโซลูชันที่อ่าน 32 ชิ้นขนาดใหญ่ 32 MB ซึ่งทำให้ 1GB:

dd if=/dev/urandom of=output bs=32M count=32

วิธีการแก้ปัญหาอื่นได้รับที่อ่าน 1 GB ตรงไปยังหน่วยความจำแล้วเขียนลงดิสก์ วิธีแก้ปัญหานี้ใช้หน่วยความจำจำนวนมากดังนั้นจึงไม่ได้ถูกเตรียมไว้ล่วงหน้า:

dd if=/dev/urandom of=output bs=1G count=1 iflag=fullblock

3
IMHO ฉันไม่คิดว่าจะมีกรณีการใช้งานที่ถูกต้องมากมายddเลย ฉันต้องการใช้head, catหรือrsyncในสถานที่ที่เกือบตลอดเวลา และคำถามของคุณหากหนึ่งในเหตุผลที่ทางเลือกมักปลอดภัยกว่า
บากูริว

@Bakuriu - ถ้าคุณแค่ต้องการสร้างไฟล์ที่เต็มไปด้วยเลขศูนย์ (หรือคุณไม่สนใจว่ามีอะไรอยู่ในนั้น) ให้ตัดทอน มันเร็วกว่ามาก
Konrad Gajewski

@KonradGajewski FYI truncate พยายามที่จะทำไฟล์แบบเบาบาง (หากมีความสำคัญ)
Xen2050

5
@Bakuriu headไม่สามารถทำงานนี้โดยไม่มี-cตัวเลือกที่ไม่ได้อยู่ใน POSIX ฉันไม่รู้รุ่นใดcatที่สามารถแก้ปัญหานี้ได้ rsyncเป็นโปรแกรมอรรถประโยชน์ที่ไม่ได้มาตรฐานอย่างสมบูรณ์ นั่นไม่ได้อยู่ที่นี่ อ่านผ่านหน้าคนของมันฉันไม่เห็นว่ามันจะสามารถแก้ปัญหานี้ได้อย่างไร
Kaz

ในทางเทคนิคแล้ว/dev/urandomไม่ได้อยู่ใน POSIX เช่นกัน ...
grawity

คำตอบ:


92

bsขนาดบัฟเฟอร์หมายถึงขนาดของการเรียกread ()เดียวที่ดำเนินการโดย dd

(ตัวอย่างเช่นทั้งสองbs=1M count=1และbs=1k count=1kจะส่งผลให้ไฟล์ 1 MiB แต่รุ่นแรกจะทำในขั้นตอนเดียวในขณะที่สองจะทำมันใน 1024 ชิ้นเล็ก ๆ )

ไฟล์ปกติสามารถอ่านได้ที่ขนาดบัฟเฟอร์เกือบทุกขนาด (ตราบใดที่บัฟเฟอร์นั้นพอดีกับ RAM) แต่อุปกรณ์และไฟล์ "เสมือน" มักจะทำงานใกล้เคียงกับการโทรแต่ละครั้งมากและมีข้อ จำกัด โดยพลการของข้อมูล อ่าน () โทร

สำหรับ/dev/urandomขีด จำกัด นี้กำหนดไว้ในurandom_read ()ในdrivers / char / random.c :

#define ENTROPY_SHIFT 3

static ssize_t
urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
{
    nbytes = min_t(size_t, nbytes, INT_MAX >> (ENTROPY_SHIFT + 3));
    ...
}

ซึ่งหมายความว่าทุกครั้งที่มีการเรียกใช้ฟังก์ชั่นมันจะยึดขนาดที่ร้องขอเป็น 33554431 ไบต์

ตามค่าเริ่มต้นซึ่งแตกต่างจากเครื่องมืออื่น ๆ ส่วนใหญ่ddจะไม่ลองอีกครั้งหลังจากได้รับข้อมูลน้อยกว่าที่ร้องขอ - คุณจะได้รับ 32 MiB และนั่นคือมัน (หากต้องการให้ลองใหม่โดยอัตโนมัติเช่นเดียวกับคำตอบของ Kamil คุณจะต้องระบุiflag=fullblock)


ยังทราบว่า "ขนาดของการอ่านที่เดียว () ว่า" หมายความว่าบัฟเฟอร์ทั้งต้องพอดีในความทรงจำในครั้งเดียวเพื่อให้บล็อกขนาดใหญ่นอกจากนี้ยังสอดคล้องกับการใช้งานหน่วยความจำขนาดใหญ่โดยDD

และมันไม่มีจุดหมายเพราะคุณมักจะไม่ได้รับประสิทธิภาพใด ๆ เมื่อขึ้นไปอยู่เหนือบล็อก ~ 16–32 MiB ~ syscalls ไม่ใช่ส่วนที่ช้าที่นี่ตัวสร้างตัวเลขแบบสุ่มคือ

head -c 1G /dev/urandom > outputดังนั้นสำหรับความเรียบง่ายเพียงแค่ใช้


7
"... โดยปกติคุณจะไม่ได้รับการแสดงใด ๆ เมื่อขึ้นไปอยู่เหนือบล็อก ~ 16–32 MiB" - จากประสบการณ์ของฉันคุณมีแนวโน้มที่จะไม่ได้รับมากหรือแม้แต่สูญเสียประสิทธิภาพที่สูงกว่า 64-128 กิโลไบต์ไบต์ ณ จุดนี้คุณจะได้รับผลตอบแทนที่ลดลงเมื่อค่าใช้จ่ายลดลงและการช่วงชิงแคชเริ่มมีบทบาท
marcelm

3
@marcelm ฉันได้ช่วยสถาปนิกออกแบบระบบที่มีประสิทธิภาพสูงซึ่งประสิทธิภาพของ IO จะดีขึ้นเมื่อขนาดบล็อกเพิ่มขึ้นเป็น 1-2 MB บล็อกและในบางกรณีถึง 8 MB หรือมากกว่านั้น ต่อ LUN และเมื่อระบบไฟล์ถูกสร้างขึ้นโดยใช้ LUN หลายขนานเพื่อรับประสิทธิภาพที่ดีที่สุดโดยใช้หลายเธรดสำหรับ IO แต่ละบล็อกมีขนาด 1 MB + อัตรา IO อย่างต่อเนื่องมากกว่า 1 GB / วินาที และนั่นคือดิสก์หมุนทั้งหมดดังนั้นฉันสามารถเห็นอาร์เรย์ประสิทธิภาพสูงของ SSD ที่กลืนหรือสร้างข้อมูลได้เร็วขึ้นและเร็วขึ้นเมื่อขนาดของบล็อกเพิ่มขึ้นเป็น 16 หรือ 32 MB บล็อก อย่างง่ายดาย อาจใหญ่กว่านี้
Andrew Henle

4
ฉันอย่างชัดเจนจะได้ทราบว่าiflag=fullblockเป็นส่วนขยายของ GNU เพื่อPOSIXddยูทิลิตี้ เนื่องจากคำถามไม่ได้ระบุลีนุกซ์ฉันคิดว่าการใช้ส่วนขยายเฉพาะลินุกซ์ควรถูกบันทึกไว้อย่างชัดเจนเพื่อมิให้ผู้อ่านในอนาคตบางคนพยายามแก้ไขปัญหาที่คล้ายกันในระบบที่ไม่ใช่ลีนุกซ์สับสน
Andrew Henle

6
@AndrewHenle Ah น่าสนใจ! ฉันทำการทดสอบอย่างรวดเร็วด้วยddบนเครื่องของฉันด้วยขนาดบล็อกตั้งแต่ 1k ถึง 512M การอ่านจาก Intel 750 SSD ประสิทธิภาพที่ดีที่สุด (ประมาณ 1300MiB / s) ทำได้ที่บล็อก 2MiB ซึ่งตรงกับผลลัพธ์ของคุณ ขนาดบล็อกที่ใหญ่ขึ้นไม่ช่วยหรือขัดขวาง การอ่านจาก/dev/zeroประสิทธิภาพที่ดีที่สุด (เกือบ 20GiB / s) อยู่ที่บล็อก 64KiB และ 128KiB; ทั้งบล็อกที่เล็กลงและบล็อกที่มีขนาดใหญ่ลดลงประสิทธิภาพโดยประมาณตรงกับความคิดเห็นก่อนหน้าของฉัน บรรทัดล่าง: มาตรฐานสำหรับสถานการณ์ที่แท้จริงของคุณ และแน่นอนว่าเราทุกคนไม่ได้เป็นมาตรฐาน/dev/random: P
marcelm

3
@ Xen2050 ฉันทำการทดสอบอย่างรวดเร็วมากขึ้นและดูเหมือนว่าddจะเร็วขึ้น strace ที่รวดเร็วแสดงให้เห็นว่าheadใช้การอ่าน 8KiB และการเขียน 4KiB สองอันซึ่งน่าสนใจ (GNU coreutils 8.26 บน Debian 9.6 / Linux 4.8) headความเร็วที่แท้จริงอยู่ระหว่างและdd bs=4k ความเร็วจะลดลง ~ 40% เมื่อเทียบกับและลง ~ 25% เมื่อเทียบกับ แน่นอนว่าการอ่านจากCPU นั้น จำกัด มากขึ้น แต่สำหรับ SSD I / O queing ก็มีบทบาทเช่นกัน มันแตกต่างกว่าที่ฉันคาดไว้มาก dd bs=8kheaddd if=/dev/zero bs=64kdd if=/dev/nvme0n1 bs=2M/dev/zero
marcelm

21

ddอาจอ่านน้อยกว่าibs(หมายเหตุ: bsระบุทั้งคู่ibsและobs) เว้นแต่iflag=fullblockจะระบุไว้ 0+1 records inระบุว่าได้อ่าน0บล็อกเต็มและบล็อก1บางส่วนแล้ว อย่างไรก็ตามบล็อกเต็มหรือบางส่วนจะเพิ่มตัวนับ

ฉันไม่รู้กลไกที่แน่นอนที่ทำให้ddอ่านบล็อกที่น้อยกว่า1Gในกรณีนี้โดยเฉพาะ ฉันเดาว่าบล็อกใดถูกอ่านไปยังหน่วยความจำก่อนที่จะถูกเขียนดังนั้นการจัดการหน่วยความจำอาจรบกวน (แต่นี่เป็นเพียงการคาดเดา) แก้ไข: คำตอบที่เกิดขึ้นพร้อมกันนี้อธิบายกลไกที่ทำให้การddอ่านบล็อกที่น้อยกว่า1Gในกรณีนี้โดยเฉพาะ

อย่างไรก็ตามฉันไม่แนะนำขนาดใหญ่เช่นbsนี้ bs=1M count=1024ผมจะใช้ สิ่งที่สำคัญที่สุดคือ: หากไม่มีiflag=fullblock ความพยายามในการอ่านอาจอ่านได้น้อยกว่าibs(เว้นแต่ibs=1ฉันคิดว่านี่จะไม่มีประสิทธิภาพเลยทีเดียว)

iflag=fullblockดังนั้นหากคุณต้องการที่จะอ่านบางส่วนจำนวนเงินที่แน่นอนของข้อมูลการใช้งาน iflagPOSIX ไม่ต้องการหมายเหตุคุณddอาจไม่รองรับ ตามคำตอบ ibs=1นี้น่าจะเป็นวิธีเดียวที่ POSIX ในการอ่านจำนวนไบต์ที่แน่นอน แน่นอนถ้าคุณเปลี่ยนแล้วคุณจะต้องคำนวณibs countในกรณีของคุณลดลงibsไปหรือน้อยกว่าอาจจะแก้ไขปัญหาได้โดยไม่ต้อง32Miflag=fullblock

ใน Kubuntu ของฉันฉันจะแก้ไขคำสั่งของคุณเช่นนี้:

dd if=/dev/urandom of=output bs=1M count=1024 iflag=fullblock
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.