2012-06-07 63 views
3

在Linux中的用戶空間程序中,我通過堆中的分配獲得了一段內存,然後將指針分發給運行在其他線程中的許多其他組件。我希望在修改所述內存時得到通知。我當然可以開發一個自定義的用戶空間解決方案,供其他組件在嘗試修改內存時使用。在我的情況下,問題是這些是遺留組件,並且他們可以在很多場合寫入內存。所以我想知道是否有類似inotify的API(在文件發生變化時得到通知)或其他方法,以便在內存更改時得到通知。如何在Linux中的內存中獲取修改通知

我考慮過使用mmap和inotify,如果更改沒有刷新,顯然不會工作。任何建議表示讚賞:-)

回答

0

唯一可以這樣工作的是一個調試硬件觀察點。

但是,如果沿着這條路線走下去,你會做錯事。

爲了在線程之間共享內存,您需要實現適當的鎖定和同步代碼。在這種情況下,您應該能夠在內存解鎖時添加更改通知。

1

CAN添加一個inotify watch它將在mmap-ed文件上的msync()上觸發。

這需要將Linux內核修補到enable support for a new inotify watch。該補丁添加了一個新標誌IN_SYNC - 在mmap-ed文件上執行msync()時觸發的新inotify事件。

修補程序已在Linux Kernel的v2.6.37上進行了測試。

From 83edf446e92c86c738337ca4a35eab48e2f4e0eb Mon Sep 17 00:00:00 2001 
From: Chinmay V S <[email protected]> 
Date: Mon, 17 Jun 2013 13:53:57 +0800 
Subject: [PATCH] Add mmap-ed file support to inotify 

This patch adds a new flag IN_SYNC. This is a new inotify event that is 
triggered whenever msync() is carried out on a mmap-ed file. 

Signed-off-by: Chinmay V S <[email protected]> 
--- 
fs/sync.c        | 5 +++++ 
include/linux/fsnotify.h    | 16 ++++++++++++++++ 
include/linux/fsnotify_backend.h  | 1 + 
include/linux/inotify.h    | 3 ++- 
mm/msync.c       | 4 ++++ 
5 files changed, 28 insertions(+), 3 deletions(-) 

diff --git a/fs/sync.c b/fs/sync.c 
index ba76b96..174c2af 100644 
--- a/fs/sync.c 
+++ b/fs/sync.c 
@@ -16,6 +16,7 @@ 
#include <linux/buffer_head.h> 
#include <linux/backing-dev.h> 
#include "internal.h" 
+#include <linux/fsnotify.h> 

#define VALID_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| \ 
      SYNC_FILE_RANGE_WAIT_AFTER) 
@@ -190,6 +191,10 @@ static int do_fsync(unsigned int fd, int datasync) 
     ret = vfs_fsync(file, datasync); 
     fput(file); 
    } 
+ 
+ if (!ret) 
+  fsnotify_sync(file->f_path.dentry); 
+ 
    return ret; 
} 

diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h 
index b10bcde..ef211fb 100644 
--- a/include/linux/fsnotify.h 
+++ b/include/linux/fsnotify.h 
@@ -224,6 +224,22 @@ static inline void fsnotify_modify(struct file *file) 
} 

/* 
+ * fsnotify_sync - file was synced 
+ */ 
+static inline void fsnotify_sync(struct dentry *dentry) 
+{ 
+ struct inode *inode = dentry->d_inode; 
+ u32 mask = FS_SYNC; 
+ 
+ if (S_ISDIR(inode->i_mode)) 
+  mask |= FS_ISDIR; 
+ 
+ fsnotify_parent(NULL, dentry, mask); 
+ fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); 
+ 
+} 
+ 
+/* 
    * fsnotify_open - file was opened 
    */ 
static inline void fsnotify_open(struct file *file) 
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h 
index 7380763..35b5cb8 100644 
--- a/include/linux/fsnotify_backend.h 
+++ b/include/linux/fsnotify_backend.h 
@@ -36,6 +36,7 @@ 
#define FS_DELETE  0x00000200 /* Subfile was deleted */ 
#define FS_DELETE_SELF  0x00000400 /* Self was deleted */ 
#define FS_MOVE_SELF  0x00000800 /* Self was moved */ 
+#define FS_SYNC   0x00001000 /* File was synced */ 

#define FS_UNMOUNT  0x00002000 /* inode on umount fs */ 
#define FS_Q_OVERFLOW  0x00004000 /* Event queued overflowed */ 
diff --git a/include/linux/inotify.h b/include/linux/inotify.h 
index d33041e..244a132 100644 
--- a/include/linux/inotify.h 
+++ b/include/linux/inotify.h 
@@ -38,6 +38,7 @@ struct inotify_event { 
#define IN_DELETE  0x00000200 /* Subfile was deleted */ 
#define IN_DELETE_SELF  0x00000400 /* Self was deleted */ 
#define IN_MOVE_SELF  0x00000800 /* Self was moved */ 
+#define IN_SYNC   0x00001000 /* File was synced */ 

/* the following are legal events. they are sent as needed to any watch */ 
#define IN_UNMOUNT  0x00002000 /* Backing fs was unmounted */ 
@@ -64,7 +65,7 @@ struct inotify_event { 
#define IN_ALL_EVENTS (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE | \ 
      IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | \ 
      IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF | \ 
-   IN_MOVE_SELF) 
+   IN_MOVE_SELF | IN_SYNC) 

/* Flags for sys_inotify_init1. */ 
#define IN_CLOEXEC O_CLOEXEC 
diff --git a/mm/msync.c b/mm/msync.c 
index 632df45..b1665ac 100644 
--- a/mm/msync.c 
+++ b/mm/msync.c 
@@ -13,6 +13,7 @@ 
#include <linux/file.h> 
#include <linux/syscalls.h> 
#include <linux/sched.h> 
+#include <linux/fsnotify.h> 

/* 
    * MS_SYNC syncs the entire file - including mappings. 
@@ -83,6 +84,9 @@ SYSCALL_DEFINE3(msync, unsigned long, start, size_t, len, int, flags) 
      get_file(file); 
      up_read(&mm->mmap_sem); 
      error = vfs_fsync(file, 0); 
+    if (!error) 
+     fsnotify_sync(file->f_path.dentry); 
+ 
      fput(file); 
      if (error || start >= end) 
       goto out; 
-- 
1.8.2 

修補程序已在Linux Kernel的v2.6.37上進行了測試。

0

您可以對RAM中的相應頁面進行保護(將其設置爲只讀),並在寫入失敗時捕獲SIGSEGV信號。在信號處理程序中,您需要設置RAM讀寫以允許寫入成功(這主要是對用戶空間中的頁面錯誤作出反應)。然後,您需要重新保護RAM以檢測下一次寫入。

這是一個硬核C代碼,它是特定於架構的(不是便攜式的),但我過去做過(2001年在英特爾奔騰服務器上)。這是x86特定的,所以我不知道如何在x86_64上執行此操作。如果需要,我可以在我的檔案中做一些考古工作,讓你朝着正確的方向前進(發表評論,我會潛入舊代碼中)。