Armadilloフォーラム

microSDにファイルが保存されない

ozawa

2020年11月18日 19時53分

お世話になります。小澤と申します。

Armadillo-IoT G3Lにおいて、microSDを外部ストレージとして使う場合について教えてください。

microSDを挿入し、ある条件のときファイルを保存するように
組込んでいますが、microSDにファイルが保存ができません。

microSDはFAT32でフォーマットしています。

下記のように、/media にマウントし、ディレクトリ(aaa)を作成し
ここにrenameしてファイルを移動するようにしています。

system("mount -t vfat /dev/mmcblk0p1 /media");
system("mkdir /media/aaa/);

Teratermで、ディレクトリ(/media/aaa/)をlsコマンドで確認したところ、ファイルが存在していましたが、
ArmadilloからmicroSDを取り外し、Windows上でmicroSDの内容確認すると、何も保存されていませんでした。

何かやり方が間違っているのでしょうか?
ちなみにArmadilloからmicroSDを取り外すとき
umount /media をすると、
”umount: /media: not mounted” と表示されました。
うまくマウントができてないのでしょうか?

ご教授のほど、よろしくお願いいたします。

コメント

古関です。

頂いている情報だけだと判断が難しいのですが、
考えられること記載します。

■ コマンドの戻り値チェック
C言語からsystem関数を実行しているものと思いますが、
mountコマンドやmkdirコマンドの戻り値チェックはしているでしょうか?
mountコマンド自体がエラーになっていないのにもかかわらず、
umount: /media: not mountedが出る状況でしょうか。

■ syncの実行
mkdir からumountの間にsyncコマンド は実行しているでしょうか?

お世話になります。小澤です。

古関様、ご返信ありがとうございます。

以下のように、mountコマンドやmkdirコマンドができているか、処理を追加して確認してみました。

~~~
LOG_INFO("===== start =====");
static string BASE_DIR = "/media/unsent/";

struct stat statBuf;
if( system("mount -t vfat /dev/mmcblk0p1 /media") ){
LOG_INFO("mount NG");
}else{
LOG_INFO("mount OK");
}
static string cmd = "mkdir " + BASE_DIR;
if( system(cmd.c_str()) ){
LOG_INFO("mkdir NG");
}else{
LOG_INFO("mkdir OK");
}

auto file_name = get_file_name(unsent_files);
auto moved_file = BASE_DIR + file_name;

if(rename(unsent_files.c_str(), moved_file.c_str()) == 0){
LOGF_INFO("moved file path:%s -> %s", unsent_files.c_str(), moved_file.c_str());
}else{
LOG_ERROR(strerror(errno));
}

~~~

上記の処理を実行すると、以下のログ出力となりました。
>>>>>>>>>>>>>>>>
[info] ===== start =====
[info] mount OK
[info] mkdir OK
[error] Invalid cross-device link
<<<<<<<<<<<<<<<<

mount、mkdirはできているが、renameコマンドができてなくて
エラー出力されているように見えます。

ちなみにこの後、umountができました。
(前回はおそらくmountがうまくできてなかったのかと思います)

このエラー「Invalid cross-device link」は
何が原因で発生しているのでしょうか?

推測ですが、
mountできてないときは、ファイル移動ができるがmicroSDに保存できない。
mountできているときは、このエラーが発生しファイル移動ができなくなる、と思われます。

ご教授のほど、よろしくお願いいたします。
もし情報が不足していましたら、ご指摘ください。

> mount、mkdirはできているが、renameコマンドができてなくて
> エラー出力されているように見えます。

そのrenameはコマンドではなくてシステムコールですね。
renameシステムコールは異なるマウントポイント間で動作しません。

Invalid cross-device linkのerrnoはEXDEVですが
(strerroで説明の文字列に変えると却ってわかりづらいですね)
man 2 renameとコマンド打ってEXDEVの説明を見ると、
そう書いてあるのがわかると思います。

(参考: rename の日本語訳)
https://linuxjm.osdn.jp/html/LDP_man-pages/man2/rename.2.html

恐らくmount した microSD と armadilloのeMMC間でrenameしようとしたので
上のエラーになっているのでしょう。
(microSD から microSD へrename等同じマウントポイントなら問題ないです)

こういう場合は下記の方法があります。
元々systemでコマンド呼んでいるのでとくに事情なければcで良いと思いますが…

a. 元、先ともにopen() して read() write()で転記して元ファイルを削除
b. sendfile()関数を使う(POSIX準拠にこだわりが無い限りaではなくbで良いです)
c. system()でmvコマンドを呼ぶ

古関様

お世話になります。小澤です。
ご教授いただきありがとうございます。

>c. system()でmvコマンドを呼ぶ

上記cの方法で、mvコマンドを使って
microSDにファイルが保存されることを確認できました。
どうもありがとうございました。