使用 DIRECT IO 将扇区写入磁盘后:
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#define SECTOR_SIZE 512
int main(int argc, char *argv[]) {
int offset = 0x2000000;
int length = 4;
int rc = -1;
char *sector = (char*) aligned_alloc(SECTOR_SIZE, length*SECTOR_SIZE);
memset(sector, 0, length*SECTOR_SIZE);
int fd=open("/dev/sdd", O_RDWR | O_DIRECT);
for (int i = 0; i < length*SECTOR_SIZE; i++) {
sector[(i)] = (i&0xFF);
}
lseek(fd, offset, SEEK_SET);
rc = write(fd, sector, length*SECTOR_SIZE);
free(sector);
close(fd);
}
每次写入扇区时,操作系统(Linux Mint 18.3,HP Elite 8000)都会重新验证。磁盘消息:
Apr 28 11:11:08 rp-mint-primary kernel: [427606.669411] scsi 4:0:0:0: Direct-Access ATA ST3160215ACE A PQ: 0 ANSI: 5
Apr 28 11:11:08 rp-mint-primary kernel: [427606.716607] sd 4:0:0:0: [sdd] 312581808 512-byte logical blocks: (160 GB/149 GiB)
Apr 28 11:11:08 rp-mint-primary kernel: [427606.716632] sd 4:0:0:0: [sdd] Write Protect is off
Apr 28 11:11:08 rp-mint-primary kernel: [427606.716636] sd 4:0:0:0: [sdd] Mode Sense: 00 3a 00 00
Apr 28 11:11:08 rp-mint-primary kernel: [427606.716655] sd 4:0:0:0: Attached scsi generic sg4 type 0
Apr 28 11:11:08 rp-mint-primary kernel: [427606.716673] sd 4:0:0:0: [sdd] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
Apr 28 11:11:08 rp-mint-primary kernel: [427606.750419] sdd: sdd1 sdd2
Apr 28 11:11:08 rp-mint-primary kernel: [427606.751102] sd 4:0:0:0: [sdd] Attached SCSI disk
Apr 28 11:16:30 rp-mint-primary kernel: [427929.080622] sdd: sdd1 sdd2
Apr 28 11:16:36 rp-mint-primary kernel: [427934.631877] sdd: sdd1 sdd2
最后一行是在每个扇区写入完成且无错误后输出的,但磁盘大约一秒钟无法访问,这导致在扇区中存储数据的循环速度大幅减慢。Mint 17 在几次访问后会停止执行此操作,但 18 永远不会停止。如果确实发生了重新验证,是否有 {ATTR} 或某些开关可以设置以停止重新验证?搜索 libata 没有找到任何帮助,作为一名硬件开发人员,我很容易迷失在这里。
顺便说一句,不要运行该程序,它将磁盘用作“超级软盘”,并且会破坏其写入扇区中的所有数据。
我找到了一些更多信息:“sdd:sdd1 sdd2”仅在硬盘上存在有效分区表时写入扇区后才会发生。如果分区表被清零,操作系统将从磁盘读取许多扇区的数据(大约 0.3 秒),并且该过程会默默退出,没有任何迹象(我找不到)表明到底发生了什么。我尝试过从所有我能找到该选项的模块中打开详细消息。
是否有一个内核调试开关可以检查特定设备的 IOCTL 事务?
答案1
发现重新验证行为来自文件管理器的“自动挂载”选项。任何时候写入设置了 O_DIRECT 的磁盘都会导致操作系统重新挂载该磁盘上的所有分区。将文件管理器行为选项卡设置为禁用自动挂载解决了我的应用程序的问题。