【发布时间】:2023-03-28 10:43:01
【问题描述】:
你可以使用
dd if=/dev/zero of=file count=1024 bs=1024
零填充文件。
我想要一个填充文件而不是那个。我该怎么做?
没有 /dev/one 文件,如何通过 bash shell 模拟这种效果?
【问题讨论】:
-
写个C程序来做,应该很简单。
你可以使用
dd if=/dev/zero of=file count=1024 bs=1024
零填充文件。
我想要一个填充文件而不是那个。我该怎么做?
没有 /dev/one 文件,如何通过 bash shell 模拟这种效果?
【问题讨论】:
tr '\0' '\377' < /dev/zero | dd bs=64K of=/dev/sdx
这应该快得多。选择您需要的块大小(或添加计数)。以 99M 的块大小将它们写入 SSD 磁盘直到写满给了我 350M/s 的写入性能。
【讨论】:
tr '\0' '\377' < /dev/zero | pv | sudo dd bs=512K of=/dev/sdx,速度约为 8MB/s。命令pv 显示完成了多少字节,以及速度。您可能需要安装它,但它非常有用。
试试这个:
dd if=<(yes $'\01' | tr -d "\n") of=file count=1024 bs=1024
如果您希望所有位都为 1,请替换 $'\377' 或 $'\xFF'。
【讨论】:
tr 以使该命令工作的方式运行
LANG(我的是 en_US.UTF-8)。
\x80 或以上的任何内容。显然它不喜欢第 8 位设置,除非LANG=C。对于那些可能不知道的人,您可以只针对tr:dd if=<(yes $'\xFF' | LANG=C tr -d "\n") of=file count=1024 bs=1024的环境这样做,它不会影响一般环境。
sudo 运行它?这是该错误的一个可能原因。如果是这样,那么这是使其工作的一种方法:sudo bash -c 'dd if=<(yes $'\01' | tr -d "\n") of=file count=1024 bs=1024'
好吧,你可以这样做:
dd if=/dev/zero count=1024 bs=1024 |
tr '\000' '\001' > file
【讨论】:
1 (01 01 01 01 ...) 的字节填充文件。使用\377 会将所有位 设置为1(所以FF FF FF FF ...)。取决于 OP 的要求。
pv /dev/zero |tr \\000 \\377 >targetfile
...其中\377 是255 的八进制表示(所有位都设置为1 的字节)。为什么tr 只适用于八进制数字,我不知道——但请注意不要下意识地将其翻译为 3FF。
使用tr 的语法容易出错。我建议验证它是否正在进行所需的翻译...
cat /dev/zero |tr \\000 \\377 |hexdump -C
注意:pv 是一个不错的实用程序,它取代了cat 并添加了进度/速率显示。
【讨论】:
dd,因为如果您不手动选择最佳@987654331,这会减慢速度(很多) @值。
pv 也会给出剩余时间的估计。
time和nice。
我在github 中创建了一个设备驱动程序。安装它会创建一个文件/dev/one,它只写入设置为 1 的位。
名为 one.c 的 c 文件(唯一有趣的部分在 device_file_read):
// File Driver to create a devince /dev/one like the /dev/zero
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
MODULE_LICENSE("GPL");
static int device_file_major_number = 0;
static const char device_name[] = "one";
static ssize_t device_file_read(
struct file *file_ptr,
char __user *user_buffer,
size_t count,
loff_t *position) {
printk( KERN_NOTICE "One: Device file is read at offset = %i, read bytes count = %u\n" , (int)*position , (unsigned int)count );
// Allocate Kernel buffer
char* ptr = (char*) vmalloc(count);
// Fill it with one, byte per byte
// -- Note that byte is the smallest accesible data unit
memset(ptr, 0xFF, count);
char res = copy_to_user(user_buffer, ptr, count);
if (res != 0){ return -EFAULT; }
// Return number of byte read
return count;
}
static struct file_operations simple_driver_fops = {
.owner = THIS_MODULE,
.read = device_file_read,
};
int register_device(void) {
int res = 0;
printk( KERN_NOTICE "One: register_device() is called.\n" );
res = register_chrdev( 0, device_name, &simple_driver_fops );
if( res < 0 ) {
printk( KERN_WARNING "One: can\'t register character device with error code = %i\n", res );
return res;
}
device_file_major_number = res;
printk( KERN_NOTICE "One: registered character device with major number = %i and minor numbers 0...255\n", device_file_major_number );
return 0;
}
void unregister_device(void) {
printk( KERN_NOTICE "One: unregister_device() is called\n" );
if(device_file_major_number != 0) {
unregister_chrdev(device_file_major_number, device_name);
}
}
static int my_init(void) {
register_device();
return 0;
}
static void my_exit(void) {
unregister_device();
return;
}
// Declare register and unregister command
module_init(my_init);
module_exit(my_exit);
Makefile
TARGET_MODULE:=one
BUILDSYSTEM_DIR:=/lib/modules/$(shell uname -r)/build
PWD:=$(shell pwd)
obj-m := $(TARGET_MODULE).o
# See: https://stackoverflow.com/questions/15910064/how-to-compile-a-linux-kernel-module-using-std-gnu99
ccflags-y := -std=gnu99 -Wno-declaration-after-statement
build:
# run kernel build system to make module
$(MAKE) -C $(BUILDSYSTEM_DIR) M=$(PWD) modules
clean:
# run kernel build system to cleanup in current directory
$(MAKE) -C $(BUILDSYSTEM_DIR) M=$(PWD) clean
rm -f MOK.priv MOK*.der
key:
echo "Creating key"
openssl req -new -x509 -newkey rsa:2048 -days 36500 -keyout MOK.priv -outform DER -out MOK.der -nodes -subj "/CN=TinmarinoUnsafe/"
#
echo "\e[31;1mPlease enter a password you will be asked for on reboot:\e[0m"
mokutil --import MOK.der
echo "\e[31;1mNow you must: 1/ reboot, 2/ Select Unroll MOK, 3/ Enter password you previously gave\e[0m"
sign:
cp one.ko one.ko.bck
/usr/src/linux-headers-$(shell uname -r)/scripts/sign-file sha256 MOK.priv MOK.der one.ko
load:
insmod ./$(TARGET_MODULE).ko
unload:
rmmod ./$(TARGET_MODULE).ko
create:
mknod /dev/one c $(shell cat /proc/devices | grep one$ | cut -d ' ' -f1) 0
delete:
rm /dev/one
test:
[ "$(shell xxd -p -l 10 /dev/one)" = "ffffffffffffffffffff" ] \
&& echo "\e[32mSUCCESS\e[0m" \
|| echo "\e[31mFAILED\e[0m"
由于驱动程序签名强制执行,安装时间较长(3 分钟)。如果您在 UEFI 中禁用它,请忽略此部分。
git clone https://github.com/tinmarino/dev_one.git DevOne && cd DevOne # Downloadmake build # Compilemake key # Generate key for signingsudo make sign # Sign driver module to permit MOK enforcement (security)sudo reboot now # Reboot and enable Mok
make sign 提供的密码
sudo make load # Loadsudo make device # Create /dev/onemake test # Test if all is ok【讨论】:
您可以在没有特殊设备的情况下模拟/dev/one,使用 FIFO + printf(循环;慢速)或yes(快速):
mkfifo ddfifo
dd if=ddfifo of=<file> iflag=fullblock count=1024 bs=1024 status=progress & while printf '\1'; do printf '\1'; done > ddfifo
或者:
mkfifo ddfifo
dd if=ddfifo of=<file> iflag=fullblock count=1024 bs=1024 status=progress & yes "" | tr '\n' '\1' > ddfifo
如果您想要所有位都设置为 1 的字节,请将 '\1' 交换为 '\377'。
【讨论】: