2016-04-13 15 views
5

Iは、Cプログラミング言語ブックカーニハンとリッチーのページ170に記載されているように、低レベルのI/O readwriteシステムは、コール使用するいくつかのコードを持っています。 関数のプロトタイプは、大量のデータを読み書きするために、より大きなFORTRANベースのプログラムによって呼び出され、これらのreadwriteを使用しています。このCローレベル読み出し書き込み機能64ビット相当?

int n_read = read (int fd, char *buf, int n) 
int n_read = write (int fd, char *buf, int n) 

今2つの.cファイルです。

Cコードは、関数名の後にアンダースコアを有し、かつ、参照渡し、いかなる種類の#includeで、単にこれです:

int read_ (int *descriptor, char *buffer, int *nbyte) 
{ 
    return (read(*descriptor, buffer, *nbyte)); 
} 

int write_ (int *descriptor, char *buffer, int *nbyte) 
{ 
    return (write(*descriptor, buffer, *nbyte)); 
} 

と大きなFORTRANベースのプログラムでは、この

ようなことを行います
INTEGER nbyte 
COMPLEX*16 matrix(*) 
INTEGER READ, WRITE 
EXTERNAL READ, WRITE 

status = READ(fd, matrix, nbyte) 
if (status .eq. -1) then 
    CALL ERROR('C call read failure') 
    stop 
endif 

あなたがすでに推測しているように、これはのnbyteの値が2^31未満で正常に動作します。私は、データの2 GB以上を読み込む必要がありますので、私はnbyte長整数INTEGER FORTRANにおける* 8する必要があります。 unistd.hとfeatures.hによって提供さlseek64があるよう

は同等read64とwrite64は、ありますか?

これを再コードする最良の方法は何ですか? 私はfreadとfwriteを使うべきですか? はfread()からFILE *streamと同じ低レベルwriteからint fdのですか?

私の要件は、100〜500ギガバイトまたはすべてnbyte

アムiの値のためのものである12桁を有する整数で、最大値を可能にするために、8バイトの長整数を通過することができるされています何を得るか、または現在「システムコール」として識別されreadwriteを用いて負け?これは何を意味するのでしょうか?

+3

すべてが読み込まれるまで、小さなチャンクで連続して読み込むのはどうですか? –

+0

K&R Cは、歴史的な理由から興味がある場合を除いて、今学ばなければならないものではありません。物事の多くは、陳腐な、時代遅れ、または間違って今日は間違っています。例えば、 'read()'関数のためのRTFMしかなければ、Leandrosがあなたに与えた宣言を見つけて、おそらくあなた自身の問題を解決したでしょう。 –

+0

それはせいぜい醜い回避策@WeatherVaneであろう。 Fortran側でCコードとのインタフェースが取れない場合は、まだ注意が必要です。 –

答えて

5

編集:あなたがすることはできません、少なくともではないLinux上で。 readは、32ビット整数が保持できるもの以上を転送することはありません。 read上のLinuxのmanページから

:Linuxの

、(読み)(および同様のシステムコールは)実際に転送されたバイト の数を返す、高々 0x7ffff000(2147479552)バイトを転送します。 (これは、32ビットと64ビットの両方 システムでも同様である。)

これはPOSIXのcontraintないが、それは、POSIXで許可さが、最終的には実装がどのread挙動定義います。 Andrew Hanleという報告では、32GBファイルの読み取りはSolaris上でうまく動作します。この場合、私の古い答えはまだ有効です。

旧回答:

readだけで罰金64ビットのファイルを扱うことができます。それは、次のよう<unistd.h>で定義されています: -

ssize_t read(int fd, void *buf, size_t count); 

あなたはsize_tの代わりintで動作するようにあなたのルーチンを調整しなければならない、適切に大きなファイルをサポートします。

大きなファイルでreadを使用する前にの最大値をチェックし、小さい場合は中止します(または小さなチャンクに分割する)。 SSIZE_MAXは実装定義の値です。

+1

'size_t'が64ビットの数値を扱えるだけの大きさを持っていることをどのように知っていますか?最大表現可能な値は65534です。 –

+1

@JohnBollinger彼はstdioではなくPOSIX APIを使用しています。 POSIXは 'size_t'が最大ファイルサイズに十分に大きくなるように要求していませんか? – Barmar

+0

@Barmar、POSIXとCはどちらも 'SIZE_MAX'を65534と小さくすることができます。http://pubs.opengroup.org/onlinepubs/009695399/basedefs/stdint.h.html –

0

@Leandrosはタイプsize_tのバイト数を受け入れ、タイプssize_tのバイト数を返し、read()write()のPOSIX準拠の実装が観察されたように。 read()write()関数がC標準で指定されていないため、実際にあなたに当てはまる定義です。しかし、それほど大きな差はありません。size_tは、intより広い必要はありません。実際、それはもっと狭くてもかまいません。

あなたはとにかく大きな問題があります。 Fortranコードは、呼び出しているC関数が指定されたバイト数を読み書きするか、失敗すると想定していますが、POSIX read()write()は成功したときにそれを行うことが保証されていません。先日、64ビットシステムで64ビットシステムを使用していても、これらの関数が符号付き32ビット整数よりも一度に多くのバイトを転送しないという事実を念頭において、ビット[s]size_t

指定されたバイトの完全な数が転送されるか、エラーが発生するまでは、基礎となるread()またはwrite()関数の連続呼び出しを行い、ループread_()write_()機能を実装することで、一石これらの鳥の両方を殺すことができます。

+0

する必要があります。 'read'は0x7ffff000バイト以上の読み込みをサポートしていません。 – Leandros

+0

@Leandros、それは私の答えで既にカバーされているいくつかの実装にも当てはまりますが、POSIXはすべての実装の真実である必要はありません。しかし、それはループすることを非常に良いアイデアにします。 –

+0

正しい。あなたは一般的に、実装されていない方法でそれに答えることはできません。 Linuxでは不可能ですが、他のPOSIX準拠のプラットフォームもサポートしています。 (ダーウィンについてここで考える) – Leandros

関連する問題