精华内容
下载资源
问答
  • Android通信之 INotify

    2018-02-25 15:56:35
    INotify INotify是Linux内核提供的一种文件系统变化通知机制。它可以为应用程序监控文件系统的变化,如文件的新建、删除、读写等。 INotify机制有两个基本对象,分别为inotify对象与watch对象,都使用文件描述符...

    INotify

    INotify是Linux内核提供的一种文件系统变化通知机制。它可以为应用程序监控文件系统的变化,如文件的新建、删除、读写等。

    INotify机制有两个基本对象,分别为inotify对象与watch对象,都使用文件描述符表示。

    inotify对象对应一个队列,应用程序可以向inotify对象添加多个监听。当被监听的事件发生时,可以通过read()函数从inotify

    对象中将事件信息读取出来。Inotify对象可以通过以下方式创建:

     int mINotifyFd = inotify_init();

    而watch对象则用来描述文件系统的变化事件的监听。它是一个二元组,包括监听目标和事件掩码两个元素。监听目标是文件系统的一个

    路径,可以是文件也可以是文件夹。而事件掩码则表示了需要监听的事件类型,掩码中的每一位代表一种事件。可以监听的事件种类很多,

    其中就包括文件的创建(IN_CREATE)与删除(IN_DELETE).

    以下代码即可将一个用于监听输入设备节点的创建与删除的对象添加到inotify对象中:

    static const char *DEVICE_PATH = "/dev/input"
    
    int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);

    完成上述watch对象的添加后,当/dev/input/下的设备节点发生创建与删除操作时,都会将相应的事件信息写入inotify对象中,此时可以

    通过read()函数从inotify描述符中将事件信息读取出来。

    事件细腻使用结构体inotify_event进行描述

    struct inotify_event {
      __s32 wd;         /* 事件对应的watch对象的描述符 */
      __u32 mask;       /* 事件类型,如文件被删除,此处的值为IN_DELETE */
      __u32 cookie;
    /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
      __u32 len;        /* name字段的长度 */
      char name[0];     /* 可变长的字段,用于存储产生事件的文件路径 */
    }

    当监听事件发生时,可以通过如下方式讲一个或多个未读取事件信息读取出来:

    int res;
    
    char event_buf[512];
    
    res = read(mINotifyFd, event_buf, sizeof(event_buf));

    其中event_buf是inotify_event的数组指针,能读取的事件量取决于数组的长度。成功读取事件信息后,便可根据inotify_event

    结构体的字段判读事件类型以及事件产生的文件路径

    总结INotify机制的使用过程

    通过inotify_init()创建一个inotify对象

    通过inotify_add_watch()将一个或多个监听添加到inotify对象中

    通过read()函数从inotify对象中读取监听事件。当没有事件发生时,inotify对象中无任何可读数据

    通过INotify机制避免了轮询文件系统的麻烦,但是INotify机制并不是通过回调的方式通知事件,而需要使用者主动从inotify对象

    中进行事件读取。

    展开全文
  • inotify in android

    千次阅读 2012-07-05 10:39:04
    android_util_FileObserver.cpp uses inotify to notice the changes of appointed files , and report these changes to FileObserver. android_os_fileobserver_init() call inotify_init to create an in

    android_util_FileObserver.cpp  uses inotify to notice the changes of appointed files , and report these changes to FileObserver.


    android_os_fileobserver_init()  call inotify_init  to create an inotify instance.  a file descriptor is returned to the caller,

    the caller will pass it  in android_os_fileobserver_startWatching, android_os_fileobserver_stopWatching etc. functions.



    static jint android_os_fileobserver_startWatching(JNIEnv* env, jobject object, jint fd, jstring pathString, jint mask): 


    The function call inotify _add_watch(fd, pathname, mask)  to  watch the inode pointed to by pathname.

    inotify _add_watch returns a unique watch descriptor to the inode pointed by the pathname.

    notes: the parameter fd is a file descriptor created by  android_os_fileobserver_init,  inotify instance.


    static void android_os_fileobserver_stopWatching(JNIEnv* env, jobject object, jint fd, jint wfd):

    the function call inotify_rm_watch to cancel a watch on the watch descriptor wfd in an inotify instance appointed by  fd .


    static void android_os_fileobserver_observe(JNIEnv* env, jobject object, jint fd):


    This function  enters into a dead loop, it  continously read event information from the  inotify instance appointed by fd.

    The function do not return unless encounter an error when reading and the error is not EINTR.

    after read events, the events is splited to single event, then call method_onEvent( it is a global variant be metioned later)  to send the event to FileObserver.



    int register_android_os_FileObserver(JNIEnv* env):

    this funtion will get method id of    "android/os/FileObserver$ObserverThread/onEvent",

    and save the method id in method_onEvent,

    and register all methods to androidruntime metioned above .

    from what the function do , we should guess the function is called very early, 

    in fact the function's address  is declared in array  gRegJNI[] (static const RegJNIRec ),

    each gRegJNI's element  is called at androidRuntime's startup. (in function startreg)





    展开全文
  • 0x0前言之前在分析某个Android平台加固壳子的时候就碰到过inotify,被用来监控/proc 文件系统,防止gdb调试器的附加,以达到反调试的目的。inotify机制是从linux kernel 2.6.13开始引入,Android 1.5对应的linux内核...

    0x0前言

    之前在分析某个Android平台加固壳子的时候就碰到过inotify,被用来监控/proc 文件系统,防止gdb调试器的附加,以达到反调试的目的。inotify机制是从linux kernel 2.6.13开始引入,Android 1.5对应的linux内核已经是2.6.26了。因此完全可以在Android上利用inotify达到反调试的目的。而且Android将inotify直接封装成了FileObserver类,可以直接在Java代码中使用。当然在jni中自己调用inotify也是很容易的。

    0x01 FileObserver 使用实例

    想要在Java层使用FileObserver,必须先继承FileObserver类,实现其onEvent()函数。作为目标文件发生变化时调用的方法。

    private class SingleFileObserver extends FileObserver{

    //......

    @Override

    public void onEvent(int i, String s) {

    //.....

    }

    }

    通过startWatching()开始监视,stopWatching()停止监视。

    考虑到FileObserver不支持子目录的递归,将FileObserver封装了一层,以达到可以递归监视的目的。

    public class RecursiveFileObserver{

    private ArrayList mSingleObservers = new ArrayList();

    public RecursiveFileObserver(String path){

    //解析子目录

    Stack pathStack = new Stack();

    pathStack.push(path);

    while (!pathStack.isEmpty()){

    String parentPath = pathStack.pop();

    if (mSingleObservers.add(new SingleFileObserver(parentPath))){

    Log.d("C&C","add observer success"+parentPath);

    }

    File parent = new File(parentPath);

    if (parent.isDirectory()){

    File[] files = parent.listFiles();

    for (int i =0;i

    File f = files[i];

    if (f.isDirectory() &&

    (f.getName().equals(".") || f.getName().equals(".."))){

    //跳过 "." ".." 目录

    }else {

    pathStack.push(f.toString());

    //pathStack.push(f.getAbsolutePath());

    Log.d("C&C","file list:"+f.toString());

    }

    }

    }

    }

    }

    public void startWatching() {

    for (int i = 0;i

    mSingleObservers.get(i).startWatching();

    }

    }

    public void stopWatching() {

    for (int i = 0;i

    mSingleObservers.get(i).stopWatching();

    }

    }

    private class SingleFileObserver extends FileObserver{

    protected String mPath ;

    protected int mMask;

    public static final int DEFAULT_MASK = CREATE | MODIFY | DELETE;

    public SingleFileObserver(String path){

    this(path , DEFAULT_MASK);

    }

    public SingleFileObserver(String path , int mask){

    super(path , mask);

    mPath = path;

    mMask = mask;

    }

    @Override

    public void onEvent(int i, String s) {

    int event = i&FileObserver.ALL_EVENTS;

    switch (event){

    case MODIFY:

    //查看是否被调试

    if (isDebugged(s)){

    Log.d("C&C","is debugged");

    }

    }

    }

    }

    }

    0x02 FileObserver 实现原理

    Android已经将linux下的inotify机制封装成了FileObserver抽象类,必须继承FileObserver类才能使用。

    android.os.FileObserver

    Monitors files (using inotify) to fire an event after files are accessed or changed by by any process on the device (including this one). FileObserver is an abstract class; subclasses must implement the event handler onEvent(int, String).

    Each FileObserver instance monitors a single file or directory. If a directory is monitored, events will be triggered for all files and subdirectories inside the monitored directory.

    An event mask is used to specify which changes or actions to report. Event type constants are used to describe the possible changes in the event mask as well as what actually happened in event callbacks.

    Android sdk的官方文档说的是监视一个目录,则该目录下所有的文件和子目录的改变都会触发监听的事件。经过测试,其实对于监听目录的子目录的文件改动,FileObserver对象是无法接收到事件回调的。

    FileObserver可以监听的类型:

    ACCESS 访问文件

    MODIFY 修改文件

    ATTRIB 修改文件属性,例如chmod 、chown等

    CLOSE_WRITE以可写属性打开的文件被关闭

    CLOSE_NOWRITE 以不可写属性被打开的文件被关闭

    OPEN 文件被打开

    MOVED_FROM 文件被移走,例如mv

    MOVED_TO 移入新文件,例如mv cp

    CREATE 创建新文件

    DELETE 删除文件,例如rm

    DELETE_SELF 自删除,一个文件在执行时删除自己

    MOVE_SELF 自移动,一个可执行文件在执行时移动自己

    CLOSE 关闭文件 = (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)

    ALL_EVENTS 上面所有的事件

    要先继承FileObserver抽象类,实现其中的OnEvent()方法

    public abstract void onEvent(int event, String path);

    在FileObserver类中封装有一个static 的线程类

    private static class ObserverThread extends Thread {

    ......

    }

    inotify初始化

    在ObserverThread类的构造方法中:

    public ObserverThread() {

    super("FileObserver");

    m_fd = init();

    }

    这里的init是native方法:

    private native int init();

    在/frameworks/base/core/jni/android_util_FileObserver.cpp中

    static jint android_os_fileobserver_init(JNIEnv* env, jobject object)

    {

    return (jint)inotify_init();

    }

    很明显,只是调用了inotify_init(),初始化inotify。

    开始监控

    使用要先调用FileObserver.startWatching()--->ObserverThread.startWatching()--->linux( inotify_add_watch() )

    public int startWatching(String path, int mask, FileObserver observer) {

    int wfd = startWatching(m_fd, path, ma

    Integer i = new Integer(wfd);

    if (wfd >= 0) {

    synchronized (m_observers) {

    m_observers.put(i, new WeakReference(observer));

    }

    }

    return i;

    }

    static jint android_os_fileobserver_startWatching(JNIEnv* env, jobject object, jint fd, jstring pathString, jint mask)

    {

    int res = -1;

    if (fd >= 0)

    {

    const char* path = env->GetStringUTFChars(pathString, NULL);

    res = inotify_add_watch(fd, path, mask); //返回监视器描述符

    env->ReleaseStringUTFChars(pathString, path);

    }

    return res;

    }

    监控过程

    在 ObserverThread 线程运行的run()方法中:

    public void run() {

    observe(m_fd);

    }

    static void android_os_fileobserver_observe(JNIEnv* env, jobject object, jint fd)

    {

    char event_buf[512];

    struct inotify_event* event;

    while (1)

    {

    int event_pos = 0;

    int num_bytes = read(fd, event_buf, sizeof(event_buf)); //读取事件

    if (num_bytes < (int)sizeof(*event))

    {

    if (errno == EINTR)

    continue;

    ALOGE("***** ERROR! android_os_fileobserver_observe() got a short event!");

    return;

    }

    while (num_bytes >= (int)sizeof(*event))

    {

    int event_size;

    event = (struct inotify_event *)(event_buf + event_pos);

    jstring path = NULL;

    if (event->len > 0)

    {

    path = env->NewStringUTF(event->name);

    }

    //调用java层ObserverThread类的OnEvent方法

    env->CallVoidMethod(object, method_onEvent, event->wd, event->mask, path);

    if (env->ExceptionCheck()) { //异常处理

    env->ExceptionDescribe();

    env->ExceptionClear();

    }

    if (path != NULL)

    {

    env->DeleteLocalRef(path);

    }

    //指向下一个inotify_event结构

    event_size = sizeof(*event) + event->len;

    num_bytes -= event_size;

    event_pos += event_size;

    }

    }

    }

    inotify_event的结构如下:

    struct inotify_event {

    __s32 wd; /* watch descriptor */

    __u32 mask; /* watch mask */

    __u32 cookie; /* cookie to synchronize two events */

    __u32 len; /* length (including nulls) of name */

    char name[0]; /* stub for possible name */

    };

    wd: 被监视目标的 watch 描述符

    mask : 事件掩码

    name: 被监视目标的路径名,文件名被0填充,使得下一个事件结构能够以4字节对齐

    len : name字符串的长度

    调用的onEvent()方法:

    public void onEvent(int wfd, int mask, String path) {

    // look up our observer, fixing up the map if necessary...

    FileObserver observer = null;

    synchronized (m_observers) { //同步代码块

    WeakReference weak = m_observers.get(wfd);

    if (weak != null) { // can happen with lots of events from a dead wfd

    observer = (FileObserver) weak.get();

    if (observer == null) {

    m_observers.remove(wfd);

    }

    }

    }

    // ...then call out to the observer without the sync lock held

    if (observer != null) { //为什么不使用同步代码块???

    try {

    observer.onEvent(mask, path); //调用FileObserver抽象类的OnEvent()方法,也就是自己实现的OnEvent()方法

    } catch (Throwable throwable) {

    Log.wtf(LOG_TAG, "Unhandled exception in FileObserver " + observer, throwable);

    }

    }

    }

    停止监控

    FileObserver.stopWatching() --> ObserverThread.stopWatching()---> linux( inotify_rm_watch() )

    static void android_os_fileobserver_stopWatching(JNIEnv* env, jobject object, jint fd, jint wfd)

    {

    inotify_rm_watch((int)fd, (uint32_t)wfd);

    }

    0x04 完整Demo下载地址

    展开全文
  • 大家在使用Android Studio导入AOSP源码的时候,可能会遇到inotify大小不足的问题,这篇文章就给大家介绍了怎么解决这个问题的方法,有需要的朋友们可以参考借鉴。
  • 问题描述: 使用Android Studio 导入AOSP源码并且indexing完,ide右上角可能抛出警告”Kernel inotify watch limit reached”。

    问题描述

    使用Android Studio 导入AOSP源码并且indexing完,ide右上角可能抛出警告”Kernel inotify watch limit reached”。

    解决方法

    打开/etc/sysctl.conf文件,在文件的末尾添加一句话:

    fs.inotify.max_user_watches = 524288

    使用以下命令使修改生效:

    sudo sysctl -p

    然后重启你的Android Studio就可以了。

    展开全文
  • 1.INotify介绍与使用INotify是一个Linux内核所提供的一种文件系统变化通知机制。它可以为应用程序监控文件系统的变化,如文件的新建、删除、读写等。INotify机制有两个基本对象,分别为inotify对象与watch对象,都...
  • 详细请参考我的技术博客:http://blog.csdn.net/allen315410/article/details/42555415
  • 之前写过几篇 Input 系统相关的分析,但是比较零散,本篇开始准备基于 Android 11 代码看一下 Android Input 子系统,首先来学习下 Linux 下的 INotify 与 Epoll 机制,这两个机制主要是对 Input 子系统下的文件节点...
  • InotifyAndroid文件监控FileObserver原理

    千次阅读 2018-01-03 16:54:23
    Inotify
  • 当我们启动 Android Studio时有时会发现有个提示。如下所示: The current inotify (7) watch limit is too low. More details. 点击这个超链接后有一篇文章讲解如何处理这个问题。原文如下所示: link ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,888
精华内容 755
关键字:

androidinotify