대용량 저장 장치로 USB 장치가 있는데 dmesg는 다음과 같습니다.
[ 4.416584] scsi 0:0:0:0: Direct-Access Adap ECU Modular ECU 1.0 PQ: 0 ANSI: 2
[ 4.420186] sd 0:0:0:0: [sda] 131072 512-byte logical blocks: (67.1 MB/64.0 MiB)
[ 4.421063] sd 0:0:0:0: [sda] Write Protect is off
[ 4.421084] sd 0:0:0:0: [sda] Mode Sense: 03 00 00 00
[ 4.422053] sd 0:0:0:0: [sda] No Caching mode page found
[ 4.422067] sd 0:0:0:0: [sda] Assuming drive cache: write through
[ 7.446823] sd 0:0:0:0: Attached scsi generic sg0 type 0
파일 시스템을 포함하지 않으며 포함해서도 안 됩니다. 설치할 필요가 없습니다. (이 경우) /dev/sda를 열어서 읽으십시오.
문제는 장치를 열고 읽을 때 처음에 원하는 것을 얻은 다음 이후의 모든 읽기에서 캐시된 데이터를 얻는다는 것입니다. 장치의 IO 표시등은 후속 읽기 후에 깜박이지 않고 첫 번째 읽기에서만 깜박이기 때문에 이러한 가정을 하고 있습니다. 물론 fread()
첫 번째 읽기와 정확히 동일한 데이터가 포함되어 있기 때문입니다 fread()
.
내 코드는 Windows에서 컴파일하고 \.\X:를 열 파일로 지정했으며 호출할 때마다 새 데이터로 데이터를 멋지게 폴링하므로 문제가 없습니다.
그래서 저는 Linux가 읽기를 캐싱/버퍼링하고 있다고 가정합니다.
내 코드는 다음과 같습니다
#define STARTBYTE 272384
#define ENDBYTE 274432
#define NUM_VARS 1024
int main() {
FILE *input = fopen("/dev/sda", "r+");
setbuf(input, NULL);
int exit = 0;
while (exit < 1) {
signed short liveBuffer[NUM_VARS];
fseek(input, STARTBYTE, SEEK_SET);
fread(liveBuffer, 2, NUM_VARS, input);
fflush(input);
// do stuff with the now filled liveBuffer data
}
fclose(input);
return 0;
}
나는 또한 을 사용 open()
하고 지정해 보았 O_DIRECT
으나 아무런 차이가 없었습니다.
이를 위해 장치(/dev/sda)를 열고 272384바이트를 찾습니다. 2048바이트를 읽습니다. 같은 위치를 다시 찾아 2048바이트를 읽는 등의 작업을 합니다.
fclose()
파일을 다시 저장 하면 open()
새로운 데이터를 얻게 됩니다. 아주 느린 것이 아니라면 말이죠. Windows에서는(켜거나 끄지 않고) 초당 약 10개의 샘플을 얻습니다. 초당 약 50개를 얻습니다.
제가 알아차린 한 가지는 컴파일된 코드를 몇 초 동안 실행한 다음 종료할 때(CTRL+C), 코드가 실행되는 동안 장치의 활동 표시등이 미친 듯이 깜박이는 것을 볼 수 있다는 것입니다.
누구든지 올바른 방향으로 나를 가리킬 수 있습니까?
며칠 동안 이런 생각을 하다가 목을 매야겠다는 생각이 들었습니다.
답변1
개입을 사용하면 문제가 약간 복잡해집니다.표준 입력 및 출력호출하고 있는 함수의 반환 코드를 무시하세요. 이를 사용하여 O_DIRECT
장치에서 새 데이터를 얻을 수 있지만 그에 따른 의무를 준수해야 합니다.
특히 검색 오프셋, 버퍼 주소 및 I/O 크기는 모두 4096의 배수(또는 장치에 따라 2의 거듭제곱)여야 합니다.
현재 liveBuffer 선언을 제거하고 시작 부분에 다음 코드를 포함하도록 코드를 수정하면 제대로 작동하는 것을 확인할 수 있습니다.
#define PAGE 4096
#define STARTBYTE (272384/PAGE*PAGE) // must align
#define OFFSET (272384-STARTBYTE)
#define ITEMSIZE (sizeof(*liveBuffer))
#define LIVEBUFSIZE ((OFFSET+NUM_VARS*ITEMSIZE+PAGE-1)/PAGE*PAGE)
signed short *liveBuffer;
if(posix_memalign((void**)&liveBuffer, PAGE, LIVEBUFSIZE)!=0)
exit(5);
if (fcntl(fileno(input), F_SETFL, O_DIRECT) == -1)
exit(6);
fread()
이제 대신 NUM_VARS를 사용해야 합니다 LIVEBUFSIZE/ITEMSIZE
. 정렬이 필요 하므로 이제 필요한 데이터를 찾으 려면 STARTBYTE
배열로 더 들어가야 합니다 . 또한 모든 호출을 변경하여 반환 코드가 올바른지 확인해야 합니다.liveBuffer
OFFSET/ITEMSIZE