2

read()SATAHDDからベーシックを作りたい/dev/sdd。Awrite()は機能しているようです。また、フラグなしで動作しread()ます。ブロックサイズに合わせる必要があることを読みました。だから私はこれを使ってブロックサイズを取得しました:write()O_DIRECT

root$ blockdev --getsize /dev/sdd
488397168

root$ blockdev --getsize64 /dev/sdd
250059350016

root$ python -c "print 250059350016.0/488397168"
512.0

ご覧のとおり、私にはルートがあります。HDDはPCIeSATAカードを介して接続されてlspci -vvおり、基本的なahci(drivers/ata/ahci.c)ドライバーを使用していることがわかります。私は64ビットのPowerArchitectureで3.2.0Linuxカーネルを使用しています。

これが私のコードです:

#define _GNU_SOURCE

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h>

int main() {

    int r;
    char *buffer, *tmp_buffer;
    // alloc more than necesarry to align the real buffer
    tmp_buffer = malloc(2*512*sizeof(char)); 
    long align = (unsigned long)tmp_buffer%512;
    printf("tmp_buffer is at: %x \% 512 = %d\n",tmp_buffer,align);

    buffer = tmp_buffer+(512-align);
    printf("buffer is at: %x \% 512 = %d\n",buffer,(unsigned long)buffer%512);

    memset(buffer,0,sizeof(512));

    // OPEN
    int fd = open("/dev/sdd",O_DIRECT | O_RDWR | O_SYNC);
    if(fd!=3) printf("fd = %d\n",fd);

    // READ
    printf("try to read and then dump buffer:\n");

    r = read(fd,buffer,sizeof(512));
    if(r == -1) printf("Error: %s\n",strerror(errno));
    else {
        // DUMP BUFFER
        int i;
        for(i=0; i<sizeof(512); i++)
            printf("%c",buffer[i]);
    }
    printf("\n");
    return 0;
}

出力は次のとおりです。

tmp_buffer is at: 1cc80010 % 512 = 16
buffer is at: 1cc80200 % 512 = 0
try to read and then dump buffer:
Error: Invalid argument

編集:Brett Haleの回答で提案されているように、ソースを更新しました。残念ながら、まだエラーが発生します。ブロックサイズを見つける私の方法は大丈夫ですか?私は正しい位置合わせをしましたか?

読んでくれてありがとう、
ファビアン

4

2 に答える 2

5

ダイレクトDMA転送では、通常、バッファを整列させる必要があります。差出人man

O_DIRECTフラグは、ユーザースペースバッファーの長さとアドレス、およびI/Oのファイルオフセットに配置制限を課す場合があります。... Linux 2.6では、512バイト境界へのアラインメントで十分です。

したがってchar buffer[512];、512バイトのアドレスに揃える必要があるかもしれません。

スタック上でこの配置を実現できない可能性があるため、次のようになります。

static char buffer[512] __attribute__ ((__aligned__ (512)));

動作する可能性があります。または、この配置がスタックで機能する可能性があります。または、x86を使用している場合は、<mm_malloc.h>組み込みのサポート関数_mm_mallocとを使用できます_mm_free

于 2012-06-12T13:16:25.153 に答える
0

ところで、アライメントは常に512バイトの倍数である必要はありません。デバイスのブロックサイズによって異なります。BLKSSZGETでioctlを使用して見つける必要があります。O_DIRECTの使用中に読み取りがこの値に揃えられていない場合、read()はEINVALで失敗します。

于 2014-11-13T18:11:22.583 に答える