4

ユーザーが USB フラッシュ ドライブを挿入または取り外す可能性のある組み込み環境があります。ドライブが取り外されたのか、それともドライブに書き込もうとしたときに他の問題があるのか​​を知りたいです。ただし、Linux は情報をバッファーに保存するだけで、エラーを表示せずに戻ります。
私が使用しているコンピューターには、2.4.26 カーネルと libc 2.3.2 が付属しています。
私はこの方法でドライブをマウントしてい
i = mount(MEMORY_DEV_PATH, MEMORY_MNT_PATH, "vfat", MS_SYNCHRONOUS, NULL);
ます:
50:/root # mount
/dev/scsi/host0/bus0/target0/lun0/part1 on /mem type vfat (rw,sync)
50:/root #

後で、ファイルをコピーしようとします。

int ifile, ofile;
ifile = open("/tmp/tmpmidi.mid", O_RDONLY);
if (ifile < 0)
{
    perror("open in");
    break;
}
ofile = open(current_file_name.c_str(), O_WRONLY | O_SYNC);
if (ofile < 0)
{
    perror("open out");
    break;
}
#define BUFSZ 256
char buffer[BUFSZ];
while (1)
{
    i = read(ifile, buffer, BUFSZ);
    if (i < 0)
    {
        perror("read");
        break;
    }
    j = write(ofile, buffer, i);
    if (j < 0)
    {
        perror("write");
        break;
    }
    if (i != j)
    {
        perror("Sizes wrong");
        break;
    }
    if (i < BUFSZ)
    {
        printf("Copy is finished, I hope\n");
        close(ifile);
        close(ofile);
        break;
    }
}

このコード スニペットを書き込み禁止の USB メモリで実行すると、結果は次のようになります。

Copy is finished, I hope

コンソールのカーネルからのエラーメッセージが殺到する中.
USBドライブを(アンマウントせずに)単に取り外した場合も同じことが起こると思います。
私もdevfsをいじりました。(REGISTERイベントを使用して)ドライブを自動的にマウントする方法を見つけましたが、メモリを引き出したときにUNREGISTERをトリガーすることはないようです。
ファイルが正常に作成されたかどうかをプログラムで判断するにはどうすればよいですか?

7 月 4 日更新: close() からの結果をチェックしないのは私のばかげた見落としでした。残念ながら、ファイルはエラーなしで閉じることができます。それで、それは助けにはなりませんでした。fsync() はどうですか? それは良い考えのように思えますが、それもエラーをキャッチしませんでした。
/sys にこんなものがあったら面白い情報があるかもしれません。2.6まで追加されなかったと思います.?.
私のフラッシュドライブの品質に関するコメントはおそらく正当なものです. 初期のものの一つです。実際、ライト プロテクト スイッチは、最近では非常にまれなようです。
過剰なオプションを使用する必要があると思います。ファイルを作成し、ドライブをアンマウントして再マウントし、ファイルが存在するかどうかを確認します。それでも問題が解決しない場合は、何かがおかしいのです。自分へのメモ: 作成しようとしているファイルがまだそこにないことを確認してください。
ところで、これはたまたま C++ プログラムです。簡単にするために編集するつもりだった .c_str() でわかります。

4

5 に答える 5

3

アプリケーションが 1 つまたは複数のファイルを USB スティックに保存し、小さな LED がオフになった直後にユーザーがスティックを引き出せるようにする場合は、次のようにする必要があります。

  1. mount()ファイルを書き込む直前の USB スティック

    このために SYNC をマウントする必要はありません。これは、低品質の USB スティックに役立ちます。

  2. 正しいコードを使用してファイルを保存します

    C の低レベル I/O での試みはまったく正しくありません。特に、 anyread()またはは、1 から要求されたサイズまでの任意の正の値であるshort countwrite()を返すことができますが、エラーの種類を示すことはありません。

  3. fsync()USBスティック上のファイル

    成功を返すことを確認します。そうであれば、データが USB スティックにヒットしたことがわかります。

  4. fsync()USB スティック上のファイルを含むディレクトリ

    成功を返すことを確認します。存在する場合、ファイルのメタデータが USB スティックにヒットしたことがわかり、ユーザーが USB スティックを抜いてもファイルにアクセスできるようになります。

  5. umount()USBスティック

    これは、USB スティックが切断される準備ができるまでブロックされるため、アプリケーションは がumount()戻るまでファイルに保存しているように見えるはずです。

    fsync()上記の sを実行した場合は、umount()すぐに実行されるはずです。ファイルシステムによっては、カーネルが実行したい簿記があるかもしれませんが、いずれにせよそれほど時間はかかりません。

それ以外はまったく信頼できません。同期アクセスを使用して VFAT パーティションをマウントすることで、特定の仮定を立てることができるかもしれませんが、それは基本的にハンドウェイブにすぎません。

root 権限でアプリケーションを実行したくない場合は、マウントとアンマウントを管理する単純な特権サービスをいつでも作成できます。ある時点で複数のアプリケーションが必要になる可能性があると思われる場合は、非常に暖かくお勧めします。中央のマウンタ/アンマウンタだけがメディアの準備ができていることを知ることができるからです。(別のアプリケーションが同じ USB メディアに同時に書き込みを行っている場合、「マウントされていません」というメッセージを返すのが遅れる可能性があります。ちなみに、USB メディアを同期的にマウントする必要がない場合、これは非常にうまく機能します。)プロセス間通信のために/var/run/、おそらくで unix ドメイン データグラム ソケットを使用します。/var/run/mounter.socket

最後に、Linux カーネルが適切に構成/sys/され、パーティションがマウントされている場合は、すべての/sys/block/sd?/ディレクトリをスキャンしてリムーバブル メディアを探すことができます。

  • /sys/block/sd?/removableゼロ以外の 10 進数の文字列が含まれます
  • /sys/block/sd?/size10 進数の文字列として、512 バイト単位のデバイス サイズが含まれます。
  • /sys/block/sd?/device/vendorベンダー名を文字列として含む
  • /sys/block/sd?/device/modelモデル名を文字列として含む

これらのエントリはハードウェア レベルであり、USB スティックが接続されて電源が供給されているときはいつでも使用できます。マウントされているかどうかは関係ありません。ユーザーが USB スティックを引き抜くと、デバイス ディレクトリ ツリー全体がすぐに消えます。

于 2012-07-04T04:52:47.963 に答える
2

すべての書き込みエラーを検出したい場合は、 の戻りコードだけでなく、write()を呼び出してfsync()(そして戻り値を確認し)、 によって報告されたエラーも確認する必要がありclose()ます。

于 2012-07-04T05:32:26.887 に答える
1

簡単な答え: 問題は OS および/または USB ドライブにあります。Linux は (ときどき?) 書き込み禁止スイッチが設定されていても、USB ドライブを書き込み可能として喜んでマウントします。ただし、実際に書き込みを試みると、ドライブは拒否し、これは多かれ少なかれ欠陥のあるドライブとして処理されます。(なぜこれが起こるのかわかりません。私の推測では、フラッシュ ドライブが読み取り専用であることを OS に報告していないのです。これは、使用しているフラッシュ ドライブのメーカーとモデルによって異なる可能性があります。)

3.2.0-26 カーネル (具体的には Ubuntu 12) の (非常に古い) USB キーで同じ動作を得ることができます。書き込み保護された USB キーを読み取り/書き込みでマウントするのに問題はなく、ファイルをコピーしても「cp」は文句を言いません。ファイルは (バッファリングのため) ディレクトリに表示されることもありますが、実際には何も書き込まれません。syslog に多くのエラー メッセージが表示されます。

もし私があなたなら、実際にフラッシュ ドライブに書き込みを試み、ドライブが実際に書き込み可能であると仮定する前に、それが成功したことを確認します。具体的には、次のことを行います。

  1. ドライブを書き込み可能としてマウントします。

  2. 一意の名前でドライブに新しいファイルを作成します。

  3. ドライブをアンマウントしてバッファを空にします。

  4. ドライブを再度マウントします。

  5. 新しいファイルがまだそこにあり、書き込んだデータが含まれているかどうかを確認してください。

  6. テスト ファイルを削除します。

API から書き込み不能なドライブを検出する方法があるかどうかを伝えるには、ハードウェアとドライバーの状態を十分に把握していません。あるかもしれませんが、わかりません。ただし、存在する場合でも、このケースは正しく動作しない USB ドライブを検出します。

アップデート:

もう少し調査を行ったところ、書き込み保護スイッチが設定されている場合、ファイル ハンドルで実行された fsync() が失敗することがわかりました。そのため、上記のアドバイスを撤回します。代わりに、ここに私のテストプログラムがあります:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

int
main(int argc, char *argv[]) {
    char *path;
    int f;
    size_t stat;
    const char *message = "Hello, world.\n";

    if (argc != 2) {
        printf("Need filename\n");
        exit(1);
    }

    path = argv[1];

    f = open(path, O_CREAT | O_WRONLY | O_SYNC, S_IRWXU);
    if (f < 0) {
        perror("open out");
        exit(1);
    }/* if */

    stat = write(f, message, strlen(message));
    if (stat < 0) {
        perror("write");
        exit(1);
    }/* if */

    stat = fsync(f);
    if (stat) {
        perror("fsync");
        exit(1);
    }

    stat = close(f);
    if (stat) {
        perror("close");
        exit(1);
    }/* if */

    printf("(Apparently) successfully wrote '%s'\n", path);
    return 0;
}

デバイスが書き込み可能でない場合、これは fsync() 呼び出しで失敗するはずです。

于 2012-07-04T05:13:40.133 に答える
0

これがPOSIXのやり方です。の戻り値がでwriteある場合、-1何かがひどく間違っていたことを確かに知っています。ただし、write返品された場合は0、問題が発生している可能性もあります。変数をチェックして、errnoここに示されている事前定義された書き込みエラーの1つと一致するかどうかを確認します:http ://www.kernel.org/doc/man-pages/online/pages/man2/write.2.html

于 2012-07-04T04:12:59.350 に答える
0

解決策が見つからない場合は、この醜いハックを試すことができます。出力ファイルを書き込んで閉じた直後に、読み取りモードで開いてみて、正しいサイズであることを確認してください。本当に正しい内容であることを確認したい場合は、書き込んだばかりのファイルと同じチェックサムがあることを確認できます。これは、OS がある種のキャッシュではなく、USB ドライブから直接ファイルを読み戻すことを前提としています。

于 2012-07-04T04:32:32.200 に答える