在Linux中一个用户空间程序,我得到一块内存经由分配从堆中,则指针被分配到很多其他线程以使用运行的其他组件的。 我想,当上述的内存块被修改,以得到通知。 我当然可以开发自定义用户空间的解决方案,当他们尝试修改内存的其他组件使用。 在我的情况的问题是,这些都是传统组件,他们可以写入内存在很多场合。 所以,我想知道是否有类似的inotify类似的API(当文件被修改得到通知)或其他方法,以便在一块内存改为得到通知。
我认为使用mmap和inotify的,而如果所做的更改不会被刷新显然是行不通的。 任何建议都赞赏:-)
你可以添加一个inotify的手表 ,这将触发的msync()对MMAP-ED文件。
这需要打补丁的Linux内核,以启用新的inotify表支持 。 该补丁增加了一个新的标志IN_SYNC -每当则msync()是在MMAP-ED文件进行时触发新的inotify事件。
补丁的Linux内核v2.6.37测试过。
From 83edf446e92c86c738337ca4a35eab48e2f4e0eb Mon Sep 17 00:00:00 2001
From: Chinmay V S <cvs268@gmail.com>
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 <cvs268@gmail.com>
---
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内核v2.6.37测试过。
你可以在MPROTECT RAM的相应页面(设置只读),当写入失败赶上SIGSEGV信号。 在信号处理程序,你需要设置RAM读写,允许写入成功(这基本上是反应页面错误在用户空间)。 然后,你就需要重新保护RAM检测下一写入。
这是硬核的C代码是体系结构相关的(不是便携式的),但我做到了,在过去(在2001年英特尔奔腾服务器)。 这是x86的具体的,所以我不知道如何与x86_64的做到这一点。 我可以做我的档案一些考古学,如果需要的定位你在正确的方向(发表评论,我会在我的旧代码潜水)。
可能的工作一样,唯一的一点是调试硬件观察点。
但是你如果你走这条路线做错了什么。
为了线程之间共享内存,你必须采取相应的锁定和同步代码。 在这你应该能够当内存被解锁加改变的通知。