网站模板 自适应,多语言的网站,手机如何开发软件,网站系统名称怎么填这段代码是一个模仿 Linux dd 命令的工具#xff0c;它用于在不同文件之间复制数据。dd 是一个非常强大的命令行工具#xff0c;可以用于数据备份、转换和复制。下面我将详细解释这段代码的原理、实现方式以及如何运行和测试。
Linux dd 命令的工作原理
dd 命令是 Unix 和 …这段代码是一个模仿 Linux dd 命令的工具它用于在不同文件之间复制数据。dd 是一个非常强大的命令行工具可以用于数据备份、转换和复制。下面我将详细解释这段代码的原理、实现方式以及如何运行和测试。
Linux dd 命令的工作原理
dd 命令是 Unix 和 Linux 系统中非常强大的文件复制和转换工具。它通过指定块大小block size来读取和写入数据实现高效的文件或设备复制。dd 命令不仅能够处理普通文件还能直接操作设备文件这使得它在系统备份、恢复和数据克隆等任务中非常有用。 基本语法dd if输入文件 of输出文件 [选项] if指定输入文件名或设备名。of指定输出文件名或设备名。[选项]各种可选参数用于控制复制行为。 常用选项 bs设置读写的块大小。例如bs4M。count复制的块数。例如count1。conv指定数据转换选项如 convsync 确保同步模式。statusprogress显示详细的进度信息。 工作流程 打开源和目标文件/设备dd 命令会先尝试打开指定的输入和输出文件或设备。按块读取和写入根据指定的块大小bsdd 从输入文件或设备读取数据并写入到输出文件或设备中。数据处理在读写过程中dd 可以根据指定的转换选项对数据进行处理如大小写转换、字节顺序转换等。重复操作上述过程会根据指定的块数count反复进行直到完成所有数据的复制或转换。
命令行使用
dd 的基本命令行格式如下
dd ifinput_file ofoutput_file [其他参数]if指定输入文件。of指定输出文件。
以下是一些常用的参数示例
bs设置块大小例如 bs1024。count设置复制的块数例如 count10。skip设置跳过的块数例如 skip5。seek设置输出文件中跳过的块数例如 seek5。
示例
复制一个文件的前 10MB 到另一个文件
dd if/dev/zero ofexample.img bs1M count10将一个磁盘分区备份到另一个磁盘分区
dd if/dev/sda of/dev/sdb基本文件复制
dd ifinputfile of ofoutputfile bs64K count1将 inputfile 复制到 outputfile每次读取和写入 64KB 的数据块只复制一个块。
备份和还原硬盘
dd if/dev/sda of/path/to/backup.img bs4M
dd if/path/to/backup.img of/dev/sdb bs4M 将整个硬盘 /dev/sda 备份到 backup.img 文件中然后将 backup.img 还原到 /dev/sdb。
创建镜像文件
dd if/dev/zero ofimagefile.img bs1G count10创建一个名为 imagefile.img 的 10GB 镜像文件内容全为零。
制作启动盘
dd ifboot.img of/dev/sdb bs4M 将 boot.img 写入到 USB 设备 /dev/sdb制作可启动的 USB 盘。
擦除硬盘数据
dd if/dev/urandom of of/dev/sda bs4M 使用随机数据覆盖整个硬盘确保数据无法恢复。
日常定位分析
dd 命令在系统恢复、数据恢复和磁盘克隆等场景中非常有用。例如当你需要从一个损坏的文件系统中恢复数据时可以使用 dd 来复制文件系统的一部分到另一个健康的磁盘上然后对复制的数据进行分析和恢复。
三、dd 命令在实际工作中的定位与分析
dd 命令因其强大的功能和灵活性在系统管理和运维工作中有着广泛的应用场景。以下是几个典型的应用场景及其分析 系统备份与恢复 场景定期备份服务器上的硬盘或分区以防数据丢失或系统故障。分析通过 dd 命令可以创建整个硬盘或分区的镜像文件方便存储和快速恢复。此外还可以使用压缩工具如 gzip进一步减小镜像文件的大小。 数据克隆和迁移 场景在更换硬盘或迁移数据时需要将旧硬盘上的数据完整复制到新硬盘。分析dd 命令可以直接操作设备文件无需经过文件系统从而提高数据复制的效率和可靠性。这对于大规模数据迁移尤其有用。 制作启动盘和恢复盘 场景需要制作可启动的 USB 盘或 CD/DVD用于系统安装或故障排查。分析dd 命令可以将 ISO 镜像文件直接写入到 USB 或光盘设备操作简单且高效。这在紧急情况下尤为重要如系统崩溃后的恢复工作。 安全删除数据 场景需要彻底删除敏感数据确保无法通过恢复工具找回。分析通过用随机数据覆盖硬盘可以有效防止数据被恢复。这种方法比单纯的文件删除更为安全适用于处理包含敏感信息的硬盘。 性能测试 场景测试磁盘的读写速度评估存储设备的性能。分析dd 命令可以生成大规模的测试数据并通过计时等方式测量磁盘的读写速度。这对于存储设备的选型和性能优化具有重要参考价值。
Linux dd 命令详解工作原理与实用指南C/C代码实现
size_t free_mem()
{uint64_t n 0;char buf[1024], found 0;FILE *f fopen(/proc/meminfo, r);if (!f)return 1024*1024;memset(buf, 0, sizeof(buf));for (;!feof(f);) {fgets(buf, sizeof(buf), f);if (strstr(buf, MemFree:)) {found 1;break;}}fclose(f);if (!found)return 1024*1024;n strtoul(buf 9, NULL, 10);if (!n)return 1024*1024;/* kB? */if (strchr(buf 9, k))n 10;else if (strchr(buf 9, M))n 20;return n/2;
}...#ifdef ANDROIDint copy_splice(struct dd_config *);int copy_splice_cores(struct dd_config *ddc)
{return copy_splice(ddc);
}#else
int copy_splice_cores(struct dd_config *ddc)
{int ifd, ofd, p[2] {-1, -1};ssize_t r 0, cpu_size 0;size_t n 0, min_bs 4096;cpu_set_t *cpu_set NULL;if (prepare_copy(ddc, ifd, ofd) 0)return -1;if ((cpu_set CPU_ALLOC(2)) NULL) {close(ifd); close(ofd);return -1;}cpu_size CPU_ALLOC_SIZE(2);CPU_ZERO_S(cpu_size, cpu_set);if (pipe(p) 0) {ddc-saved_errno errno;close(ifd); close(ofd);close(p[0]); close(p[1]);return -1;}#ifdef F_SETPIPE_SZfor (n 29; n 20; --n) {if (fcntl(p[0], F_SETPIPE_SZ, 1n) ! -1)break;}
#endifn ddc-bs;if (fork() 0) {/* bind to CPU#0 */CPU_SET_S(ddc-cores - 1, cpu_size, cpu_set);sched_setaffinity(0, cpu_size, cpu_set);close(p[0]);for (;ddc-b_in ! ddc-count !sigint;) {if (n ddc-count - ddc-b_in)n ddc-count - ddc-b_in;r splice(ifd, NULL, p[1], NULL, n, SPLICE_F_MORE|SPLICE_F_NONBLOCK);if (r 0)break;if (r 0) {if (errno ! EAGAIN)break;/* If running out of pipe buffer, decrease bs */r 0;n min_bs;}ddc-b_in r;}exit(0);}/* bind to CPU#1 */CPU_SET_S(ddc-cores - 2, cpu_size, cpu_set);sched_setaffinity(0, cpu_size, cpu_set);for (;ddc-b_out ! ddc-count;) {r splice(p[0], NULL, ofd, NULL, n, SPLICE_F_MORE);if (r 0) {ddc-saved_errno errno;break;}ddc-b_out r;ddc-rec_out;}ddc-rec_in ddc-rec_out;close(ifd);close(ofd);close(p[0]);close(p[1]);wait(NULL);if (r 0)return -1;return 0;
}
#endifint copy_splice(struct dd_config *ddc)
{
...if (prepare_copy(ddc, ifd, ofd) 0)return -1;if (pipe(p) 0) {ddc-saved_errno errno;close(ifd); close(ofd);close(p[0]); close(p[1]);return -1;}#ifdef F_SETPIPE_SZfor (n 29; n 20; --n) {if (fcntl(p[0], F_SETPIPE_SZ, 1n) ! -1)break;}
#endifn ddc-bs;for (;ddc-b_out ! ddc-count !sigint;) {if (n ddc-count - ddc-b_out)n ddc-count - ddc-b_out;r splice(ifd, NULL, p[1], NULL, n, SPLICE_F_MORE);if (r 0) {ddc-saved_errno errno;break;}ddc-rec_in;r splice(p[0], NULL, ofd, NULL, r, SPLICE_F_MORE);if (r 0) {ddc-saved_errno errno;break;}ddc-b_out r;ddc-rec_out;}close(ifd);close(ofd);close(p[0]);close(p[1]);if (r 0)return -1;return 0;
}int copy_mmap(struct dd_config *ddc)
{
...if (prepare_copy(ddc, ifd, ofd) 0)return -1;if (ddc-fsize ! (off_t)-1) {if (ftruncate(ofd, ddc-fsize) 0) {ddc-saved_errno errno;close(ifd);close(ofd);return -1;}}for (;ddc-b_out ! ddc-count !sigint;) {n ddc-mmap;bs ddc-bs;if (n ddc-count - ddc-b_out)n ddc-count - ddc-b_out;if (bs n)bs n;if (ddc-fsize (off_t)-1) {if (ftruncate(ofd, ddc-b_out n) 0) {ddc-saved_errno errno;break;}}addr mmap(NULL, n, PROT_WRITE, MAP_SHARED, ofd, ddc-b_out ddc-skip);if (addr MAP_FAILED) {ddc-saved_errno errno;break;}for (i 0; i n; i r) {if (i bs n)bs n - i;r read(ifd, addr i, bs);if (r 0) {ddc-saved_errno errno;munmap(addr, n);break;}ddc-b_out r;ddc-rec_in;}...}if (ddc-fsize ! ddc-b_out)ftruncate(ofd, ddc-b_out);close(ifd);close(ofd);if (r 0 || addr MAP_FAILED)return -1;return 0;
}int copy_sendfile(struct dd_config *ddc)
{
...off ddc-skip;n ddc-bs;for (;ddc-b_out ddc-count !sigint;) {if (n ddc-count - ddc-b_out)n ddc-count - ddc-b_out;r sendfile(ofd, ifd, off, n);if (r 0) {ddc-saved_errno errno;ret -1;break;}ddc-rec_in; ddc-rec_out;ddc-b_in r;ddc-b_out r;}close(ifd);close(ofd);return ret;
}int copy(struct dd_config *ddc)
{
...if (ddc-cores)r copy_splice_cores(ddc);else if (ddc-mmap)r copy_mmap(ddc);else if (ddc-sf)r copy_sendfile(ddc);elser copy_splice(ddc);ddc-t_end time(NULL);/* 避免div为零 */if (ddc-t_start ddc-t_end)ddc-t_end;return r;
}void print_stat(const struct dd_config *ddc)
{
...#ifdef ANDROIDfprintf(stderr, %llu records in\n%llu records out\n%llu bytes (%llu MB) copied, %lu s, %f MB/s [%f mB/s]\n,ddc-rec_in, ddc-rec_out, ddc-b_out, ddc-b_out/(120),ddc-t_end - ddc-t_start,((double)(ddc-b_out/(120)))/(ddc-t_end - ddc-t_start),((double)(ddc-b_out/(1000*1000)))/(ddc-t_end - ddc-t_start));
#elsefprintf(stderr, %lu records in\n%lu records out\n%lu bytes (%lu MB) copied, %lu s, %f MB/s [%f mB/s]\n,ddc-rec_in, ddc-rec_out, ddc-b_out, ddc-b_out/(120),ddc-t_end - ddc-t_start,((double)(ddc-b_out/(120)))/(ddc-t_end - ddc-t_start),((double)(ddc-b_out/(1000*1000)))/(ddc-t_end - ddc-t_start));
#endif}void sig_int(int x)
{fprintf(stderr, SIGINT! Aborting ...\n);sigint 1;return;
}int main(int argc, char **argv)
{
...config.bs 116;config.in /dev/stdin;config.out /dev/stdout;/* 模拟“dd”参数解析 */for (i 1; i argc; i) {if (strcmp(argv[i], -h) 0 ||strcmp(argv[i], --help) 0)usage(argv[0]);memset(buf, 0, sizeof(buf));if (sscanf(argv[i], if%1023c, buf) 1)config.in strdup(buf);else if (sscanf(argv[i], of%1023c, buf) 1)config.out strdup(buf);else if (sscanf(argv[i], skip%1023c, buf) 1)config.skip strtoul(buf, NULL, 10);else if (sscanf(argv[i], seek%1023c, buf) 1)config.seek strtoul(buf, NULL, 10);else if (sscanf(argv[i], count%1023c, buf) 1)config.count strtoul(buf, NULL, 10);else if (sscanf(argv[i], mmap%1023c, buf) 1) {if (!config.cores) {/* Size in MB */config.mmap strtoul(buf, NULL, 10);config.mmap 20;}} else if (sscanf(argv[i], cores%1023c, buf) 1) {config.cores strtoul(buf, NULL, 10);if (config.cores 2)config.cores 2;config.mmap 0;} else if (strcmp(argv[i], send) 0) {config.sf 1;} else if (strcmp(argv[i], direct) 0) {config.direct 1;} else if (sscanf(argv[i], bs%1023c, buf) 1) {config.bs strtoul(buf, NULL, 10);} else if (strcmp(argv[i], bs) 0) {config.bs 0;} else if (strcmp(argv[i], quiet) 0) {config.quiet 1;} else if (strcmp(argv[i], nosync) 0) {config.nosync 1;}}...return 0;
}
If you need the complete source code, please add the WeChat number (c17865354792)
编译完成后你可以使用以下命令行参数来测试它 ./linux_dd ifinput_file ofoutput_file [其他参数] 例如你可以使用以下命令来复制一个文件 ./linux_dd if/dev/stdin of/dev/stdout bs1024 count1024 这个命令会从标准输入读取数据并将数据写入到标准输出每次复制 1024 字节总共复制 1024 次。
代码中提供了多种复制策略 splice(2)使用 Linux 的 splice 系统调用来在管道和文件之间传输数据这种方式可以有效地利用内核缓冲区减少数据复制过程中的上下文切换。 mmap(2)通过内存映射的方式直接在内存中操作文件数据这种方式适用于大块数据的复制。 sendfile(2)在内核层面直接将数据从一个文件描述符传输到另一个减少了数据在用户空间的拷贝。 多核处理代码还支持将数据复制任务分配到多个 CPU 核心上以提高复制效率。
补充内容
安全性在使用 dd 时一定要小心指定正确的输入和输出文件错误的命令可能会导致数据丢失。效率选择合适的块大小可以显著影响 dd 的性能。通常较大的块大小可以提高复制速度。错误处理dd 命令在执行过程中可能会遇到错误了解如何解读错误信息对于解决问题至关重要。日志记录dd 命令执行时可以重定向输出到日志文件以便于事后分析。进度监控可以通过 statusprogress 参数来监控 dd 命令的执行进度。
结语
dd 命令是一个功能强大的工具它在 Linux 系统中扮演着重要的角色。了解其工作原理和使用方法可以帮助你更有效地管理和操作数据。在使用时务必谨慎以避免不必要的数据损失。
Welcome to follow WeChat official account【程序猿编码】