dd đang tạo một tệp ngẫu nhiên 32 MB thay vì 1 GB


50

Tôi muốn tạo một tệp ngẫu nhiên 1 GB, vì vậy tôi đã sử dụng lệnh sau.

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

Nhưng thay vào đó, mỗi lần tôi khởi chạy lệnh này, tôi nhận được một tệp 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

Chuyện gì thế?

BIÊN TẬP:

Nhờ những câu trả lời tuyệt vời trong chủ đề này, tôi đã đưa ra giải pháp đọc 32 khối lớn 32 MB, tạo ra 1GB:

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

Một giải pháp khác được đưa ra là đọc 1 GB thẳng vào bộ nhớ và sau đó ghi vào đĩa. Giải pháp này chiếm rất nhiều bộ nhớ nên không bị ảnh hưởng:

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

3
IMHO Tôi không nghĩ có nhiều trường hợp sử dụng hợp lệ cho ddtất cả. Tôi sẽ sử dụng head, cathoặc rsyncở vị trí của nó hầu như luôn luôn. Và câu hỏi của bạn nếu một trong những lý do tại sao các lựa chọn thay thế thường an toàn hơn.
Bakuriu

@Bakuriu - đồng thời, nếu bạn chỉ muốn tạo một tệp chứa đầy số không (hoặc đúng hơn là bạn không quan tâm đến những gì bên trong nó), hãy sử dụng cắt ngắn. Nó nhanh hơn nhiều.
Konrad Gajewski

@KonradGajewski Cắt ngắn FYI cố gắng tạo một tệp thưa thớt (nếu có vấn đề)
Xen2050

5
@Bakuriu headkhông thể thực hiện nhiệm vụ này mà không có -ctùy chọn không có trong POSIX . Tôi không biết bất kỳ phiên bản catnào có thể giải quyết điều này. rsynclà một tiện ích hoàn toàn phi tiêu chuẩn. Đó không phải là ở đây nr ở đó; lướt qua trang người đàn ông của nó, tôi cũng không thấy nó có thể giải quyết vấn đề này như thế nào.
Kaz

Về mặt kỹ thuật, /dev/urandomkhông phải trong POSIX ...
grawity

Câu trả lời:


92

bs, kích thước bộ đệm, nghĩa là kích thước của một lệnh gọi read () được thực hiện bởi dd.

(Ví dụ: cả hai bs=1M count=1bs=1k count=1ksẽ dẫn đến tệp 1 MiB, nhưng phiên bản đầu tiên sẽ thực hiện trong một bước duy nhất, trong khi phiên bản thứ hai sẽ thực hiện trong 1024 khối nhỏ.)

Các tệp thông thường có thể được đọc ở gần như bất kỳ kích thước bộ đệm nào (miễn là bộ đệm đó phù hợp với RAM), nhưng các thiết bị và tệp "ảo" thường hoạt động rất gần với các cuộc gọi riêng lẻ và có một số hạn chế tùy ý về số lượng dữ liệu chúng sẽ tạo ra cho mỗi đọc () gọi.

Đối với /dev/urandom, giới hạn này được xác định trong urandom_read () trong trình điều khiển / 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));
    ...
}

Điều này có nghĩa là mỗi khi hàm được gọi, nó sẽ kẹp kích thước được yêu cầu thành 33554431 byte.

Theo mặc định, không giống như hầu hết các công cụ khác, dd sẽ không thử lại sau khi nhận được ít dữ liệu hơn yêu cầu - bạn nhận được 32 MiB và đó là nó. (Để làm cho nó thử lại tự động, như trong câu trả lời của Kamil, bạn sẽ cần chỉ định iflag=fullblock.)


Cũng lưu ý rằng "kích thước của một lần đọc ()" có nghĩa là toàn bộ bộ đệm phải vừa trong bộ nhớ cùng một lúc, vì vậy kích thước khối lớn cũng tương ứng với mức sử dụng bộ nhớ lớn của dd .

Và tất cả đều vô nghĩa vì bạn thường sẽ không đạt được bất kỳ hiệu suất nào khi vượt lên trên ~ 16 khối32 Khối MiB - tòa nhà không phải là phần chậm ở đây, trình tạo số ngẫu nhiên là.

Vì vậy, để đơn giản, chỉ cần sử dụng head -c 1G /dev/urandom > output.


7
"... bạn thường sẽ không đạt được bất kỳ hiệu suất nào khi vượt lên trên ~ 16 khối3232 MiB" - Theo kinh nghiệm của tôi, bạn có xu hướng không đạt được nhiều, hoặc thậm chí mất hiệu suất trên 64-128 kilo byte. Tại thời điểm đó, bạn đang có lợi nhuận giảm dần, chi phí xây dựng và việc tranh chấp bộ đệm bắt đầu đóng một vai trò.
marcelm

3
@marcelm Tôi đã giúp kiến ​​trúc sư các hệ thống hiệu suất cao trong đó hiệu suất IO sẽ cải thiện khi kích thước khối tăng lên 1-2 khối và trong một số trường hợp lên tới 8 MB hoặc hơn. Mỗi LUN. Và khi các hệ thống tập tin được xây dựng bằng nhiều LUN song song, để có được hiệu suất tốt nhất có nghĩa là sử dụng nhiều luồng cho IO, mỗi luồng thực hiện 1 khối + MB. Tốc độ IO được duy trì là hơn 1 GB / giây. Và đó là tất cả các đĩa quay, vì vậy tôi có thể thấy các mảng SSD hiệu suất cao nuốt hoặc tạo dữ liệu nhanh hơn và nhanh hơn khi kích thước khối tăng lên 16 hoặc thậm chí 32 MB. Dễ dàng. Có thể còn lớn hơn.
Andrew Henle

4
Tôi sẽ lưu ý rõ ràng rằng đó iflag=fullblocklà một phần mở rộng GNU cho tiện ích POSIXdd . Vì câu hỏi không chỉ định Linux, tôi nghĩ rằng việc sử dụng các tiện ích mở rộng dành riêng cho Linux có lẽ nên được lưu ý rõ ràng vì sợ một số độc giả tương lai đang cố gắng giải quyết vấn đề tương tự trên hệ thống không phải Linux.
Andrew Henle

6
@AndrewHenle Ah, thú vị! Tôi đã thực hiện một thử nghiệm nhanh với ddmáy của mình, với kích thước khối từ 1k đến 512M. Đọc từ SSD Intel 750, hiệu suất tối ưu (khoảng 1300MiB / giây) đã đạt được ở các khối 2MiB, gần như phù hợp với kết quả của bạn. Kích thước khối lớn hơn không giúp đỡ cũng không bị cản trở. Đọc từ /dev/zero, hiệu suất tối ưu (gần 20GiB / giây) là ở các khối 64KiB và 128KiB; cả khối nhỏ hơn lớn hơn đều giảm hiệu suất, gần như phù hợp với nhận xét trước đây của tôi. Tóm lại: điểm chuẩn cho tình hình thực tế của bạn. Và tất nhiên, cả hai chúng tôi đều không có điểm chuẩn /dev/random: P
marcelm

3
@ Xen2050 Tôi đã thực hiện một số thử nghiệm nhanh hơn và nó xuất hiện ddnhanh hơn. Một bước tiến nhanh cho thấy headsử dụng 8KiB đọc và hai lần ghi 4KiB, điều này rất thú vị (GNU coreutils 8.26 trên Debian 9.6 / Linux 4.8). headtốc độ thực sự ở đâu đó giữa dd bs=4kdd bs=8k. headtốc độ giảm ~ 40% so với dd if=/dev/zero bs=64kvà giảm ~ 25% so với dd if=/dev/nvme0n1 bs=2M. Việc đọc từ /dev/zerotất nhiên bị giới hạn CPU nhiều hơn, nhưng đối với hàng đợi I / O của SSD cũng đóng một vai trò. Đó là một sự khác biệt lớn hơn tôi mong đợi.
marcelm

21

ddcó thể đọc ít hơn ibs(lưu ý: bschỉ định cả hai ibsobs), trừ khi iflag=fullblockđược chỉ định. 0+1 records inchỉ ra rằng 0khối đầy đủ và khối 1một phần đã được đọc. Tuy nhiên, bất kỳ khối đầy đủ hoặc một phần làm tăng bộ đếm.

Tôi không biết cơ chế chính xác làm cho việc ddđọc một khối nhỏ hơn 1Gtrong trường hợp cụ thể này. Tôi đoán bất kỳ khối nào được đọc vào bộ nhớ trước khi nó được ghi, vì vậy việc quản lý bộ nhớ có thể gây trở ngại (nhưng đây chỉ là phỏng đoán). Chỉnh sửa: câu trả lời đồng thời này giải thích cơ chế giúp ddđọc một khối nhỏ hơn 1Gtrong trường hợp cụ thể này.

Dù sao, tôi không khuyên bạn nên lớn như vậy bs. Tôi sẽ sử dụng bs=1M count=1024. Điều quan trọng nhất là: không có iflag=fullblock bất kỳ nỗ lực đọc nào có thể đọc ít hơn ibs(trừ khi ibs=1, tôi nghĩ, điều này khá không hiệu quả).

Vì vậy, nếu bạn cần đọc một số lượng dữ liệu chính xác, sử dụng iflag=fullblock. Lưu ý iflaglà không bắt buộc bởi POSIX, bạn ddcó thể không hỗ trợ nó. Theo câu trả lời ibs=1 này có lẽ là cách POSIX duy nhất để đọc một số byte chính xác. Tất nhiên nếu bạn thay đổi ibsthì bạn sẽ cần phải tính toán lại count. Trong trường hợp của bạn giảm ibsxuống 32Mhoặc ít hơn có thể sẽ khắc phục vấn đề, ngay cả khi không có iflag=fullblock.

Trong Kubfox của tôi, tôi sẽ sửa lệnh của bạn như thế này:

dd if=/dev/urandom of=output bs=1M count=1024 iflag=fullblock
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.