web-dev-qa-db-ja.com

inotifyを使用する適切な方法は何ですか?

Linuxでinotifyメカニズムを使用したい。ファイルaaaがいつ変更されたかをアプリケーションに知らせてほしい。その方法のサンプルを提供していただけますか?

25
dubila

inotify C API

inotifyは、あらゆる種類のファイルシステムモニターを構築するための3つのシステムコールを提供します。

  • inotify_init()はカーネルにinotifyサブシステムのインスタンスを作成し、成功するとファイル記述子を返し、失敗すると_-1_を返します。他のシステムコールと同様に、inotify_init()が失敗した場合は、errnoで診断を確認してください。
  • inotify_add_watch()は、その名前が示すように、watchを追加します。各ウォッチは、パス名と関連イベントのリストを提供する必要があります。各イベントは、_IN_MODIFY_などの定数で指定されます。複数のイベントを監視するには、各イベント間で論理演算子またはCのパイプ(|)演算子を使用します。 inotify_add_watch()が成功すると、呼び出しは登録されたウォッチの一意の識別子を返します。それ以外の場合は、_-1_を返します。識別子を使用して、関連するウォッチを変更または削除します。
  • inotify_rm_watch()はウォッチを削除します。

read()およびclose()システムコールも必要です。 inotify_init()によって生成された記述子を指定して、read()を呼び出してアラートを待ちます。典型的なファイル記述子を想定すると、アプリケーションは、ストリーム内のデータとして表されるイベントの受信を保留しています。 inotify_init()から得られたファイル記述子の一般的なclose()は、すべてのアクティブなウォッチとinotifyインスタンスに関連付けられたすべてのメモリを削除して解放します。 (典型的な参照カウントの警告もここに適用されます。インスタンスに関連付けられたすべてのファイル記述子は、監視およびinotifyによって消費されたメモリが解放される前に閉じられなければなりません。)

_#include "inotify.h"  
#include "inotify-syscalls.h"  
int wd;   
wd = inotify_add_watch (fd,   
            "/home/rlove/Desktop", IN_MODIFY | IN_CREATE | IN_DELETE);
if (wd < 0)
      perror ("inotify_add_watch");
_

この例では、変更、ファイルの作成、またはファイルの削除のために、ディレクトリ/ home/rlove/Desktopに監視を追加します。

28
joschi

以下は、inotifyを使用して「aaa」を視聴する方法のスニペットです。これはテストしておらず、コンパイルすらしていないことに注意してください!エラーチェックを追加する必要があります。

ブロッキング読み取りを使用する代わりに、inotdでpoll/selectを使用することもできます。

const char *filename = "aaa";
int inotfd = inotify_init();

int watch_desc = inotify_add_watch(inotfd, filename, IN_MODIFY);

size_t bufsiz = sizeof(struct inotify_event) + PATH_MAX + 1;
struct inotify_event* event = malloc(bufsiz);

/* wait for an event to occur */
read(inotfd, event, bufsiz);

/* process event struct here */
12
Fabian

必要なのがコマンドラインアプリケーションだけである場合、inotifywaitを使用してファイルを監視するinotifyというアプリケーションがあります。

ターミナル1から

# touch cheese
# while inotifywait -e modify cheese; do 
>   echo someone touched my cheese
> done

ターミナル2から

echo lol >> cheese

これがターミナル1で見られるものです

Setting up watches.
Watches established.
cheese MODIFY 
someone touched my cheese
Setting up watches.
Watches established.

更新:注意して使用し、コメントを参照してください。

5
activedecay

最初の質問ではQtをタグとして言及しているようですので、ここでいくつかのコメントを参照してください。

誰かがQtでそれを行う方法を知りたい場合は、Qtバージョンについて http://doc.qt.io/qt-5/qfilesystemwatcher.html を参照してください。 Linuxでは、Inotifyのサブセットを使用します(使用可能な場合)。詳細については、Qtページの説明を参照してください。

基本的に、必要なコードは次のようになります。

mainwindow.hに以下を追加します。

QFileSystemWatcher * watcher;
private slots:
    void directoryChanged(const QString & path);
    void fileChanged(const QString & path);

およびmainwindow.cppの場合:

#include <QFileInfo>
#include <QFileSystemWatcher>

watcher = new QFileSystemWatcher(this);
connect(watcher, SIGNAL(fileChanged(const QString &)), this, SLOT(fileChanged(const QString &)));
connect(watcher, SIGNAL(directoryChanged(const QString &)), this, SLOT(directoryChanged(const QString &)));
watcher->addPath("/tmp/"); // watch directory
watcher->addPath("/tmp/a.file");  // watch file

また、ファイル/ディレクトリの変更が通知された場合に呼び出されるmainwindow.cppにスロットを追加します。

void MainWindow::directoryChanged(const QString & path) {
     qDebug() << path;
}
void MainWindow::fileChanged(const QString & path) {
     qDebug() << path;
}
0
user2567875