2010-10-31 2 views
15

Tôi muốn sử dụng cơ chế inotify trên Linux. Tôi muốn ứng dụng của tôi biết khi nào một tệp aaa đã được thay đổi. Bạn có thể vui lòng cung cấp cho tôi một mẫu làm thế nào để làm điều đó?Làm thế nào để sử dụng inotify?

Trả lời

18

C API inotify
inotify cung cấp ba hệ thống gọi để xây dựng màn hình hệ thống tập tin của tất cả các loại:

  • inotify_init() tạo ra một thể hiện của hệ thống con inotify trong kernel và trả về một bộ mô tả tập tin thành công và -1 trên thất bại. Giống như các cuộc gọi hệ thống khác, nếu inotify_init() không thành công, hãy kiểm tra errno để chẩn đoán.
  • inotify_add_watch(), như tên gọi của nó, thêm đồng hồ. Mỗi đồng hồ phải cung cấp tên đường dẫn và danh sách các sự kiện thích hợp, trong đó mỗi sự kiện được chỉ định bởi một hằng số, chẳng hạn như IN_MODIFY. Để giám sát nhiều sự kiện, chỉ cần sử dụng toán tử logic hoặc — pipe (|) trong C — giữa mỗi sự kiện. Nếu inotify_add_watch() thành công, cuộc gọi sẽ trả về một mã định danh duy nhất cho đồng hồ đã đăng ký; ngược lại, nó trả về -1. Sử dụng số nhận dạng để thay đổi hoặc xóa đồng hồ được liên kết.
  • inotify_rm_watch() xóa đồng hồ.

Lệnh gọi hệ thống đọc() và đóng() cũng là cần thiết. Với mô tả được tạo ra bởi inotify_init(), gọi read() để chờ cảnh báo. Giả sử một bộ mô tả tập tin điển hình, các khối ứng dụng đang chờ nhận các sự kiện, được biểu diễn dưới dạng dữ liệu trong luồng. Dấu đóng chung() trên bộ mô tả tệp được sinh ra từ inotify_init() xóa và giải phóng tất cả các đồng hồ đang hoạt động cũng như tất cả bộ nhớ liên kết với cá thể inotify. (Các đặc trưng tính tham khảo caveat áp dụng ở đây cũng vậy. Tất cả các mô tả tập tin liên quan đến một thể hiện phải được đóng trước khi bộ nhớ tiêu thụ bởi những chiếc đồng hồ và bởi inotify được giải phóng.)

#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"); 

Ví dụ này cho biết thêm một chiếc đồng hồ trên thư mục/home/rlove/Desktop cho bất kỳ sửa đổi, sáng tạo hoặc xóa tập tin tập tin.

+0

Có lý do cụ thể nào khiến cả bạn và Fabian chọn không đưa ra các ví dụ cho kịch bản shell của inotify? – puk

+3

inotify chính nó là một API hạt nhân Linux và không phải là một chương trình không gian người dùng bạn có thể sử dụng trong một kịch bản shell. Nếu bạn muốn sử dụng API inotify trong các script của bạn, hãy xem các công cụ inotify (https://github.com/rvoicilas/inotify-tools/wiki/). – joschi

+0

Tôi chỉ sử dụng inotifywait/watch cho các thư mục của mình (thông qua các kịch bản lệnh shell). Có gì sai với hai cái này không? – puk

9

Dưới đây là một đoạn trích về cách bạn có thể sử dụng inotify để xem "aaa". Lưu ý rằng tôi đã không thử nghiệm này, tôi thậm chí không biên dịch nó! Bạn sẽ cần phải thêm lỗi kiểm tra nó.

Thay vì sử dụng tính năng chặn đọc, bạn cũng có thể sử dụng cuộc thăm dò/chọn trên inotfd.

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 */ 
+0

⁺¹ để đề cập đến Qt, những người nhìn ở đây từ đầu ra của công cụ tìm kiếm có thể thấy, rằng trang không liên quan gì đến Qt. –

0

Vì câu hỏi đầu tiên dường như đề cập đến thẻ như được ghi trong một số nhận xét ở đây, công cụ tìm kiếm có thể dẫn bạn đến đây.

Nếu ai đó muốn biết cách thực hiện bằng Qt, hãy xem http://doc.qt.io/qt-5/qfilesystemwatcher.html cho phiên bản Qt. Trên Linux, nó sử dụng một tập hợp con của Inotify, nếu nó có sẵn, hãy xem giải thích trên trang Qt để biết chi tiết.

Về cơ bản mã cần thiết trông như sau:

trong mainwindow.h add:

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

và cho 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 

cũng thêm khe trong mainwindow.cpp được gọi nếu một tập tin/thư mục thay đổi được nhận thấy:

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