您的位置:首页 > 编程语言 > PHP开发

高通LCD与TP模块间交互之callback机制(内核通知链)

2016-11-13 11:46 417 查看
1、需求分析:



在开发过程中经常需要tp与lcd做交互,而内核通知链是在内核中使用较为频繁的一种方式。

2、通知链有四种类型:



原子通知链( Atomic notifier chains):通知链元素的回调函数(当事件发生时要执行的函数)只能在中断上下文中运行,不允许阻塞。对应的链表头结构:

struct atomic_notifier_head

{

    spinlock_tlock;

    structnotifier_block *head;

};

 
可阻塞通知链( Blocking notifier chains):通知链元素的回调函数在进程上下文中运行,允许阻塞。对应的链表头:

struct blocking_notifier_head

{

    structrw_semaphore rwsem;

    structnotifier_block *head;
};

在笔者的开发过程中就是使用的这种方式。

 
原始通知链( Raw notifier chains):对通知链元素的回调函数没有任何限制,所有锁和保护机制都由调用者维护。对应的链表头:

struct raw_notifier_head

{

    structnotifier_block *head;

};

 
SRCU 通知链( SRCU notifier chains ):可阻塞通知链的一种变体。对应的链表头:

struct srcu_notifier_head

{

    struct mutexmutex;

    structsrcu_struct srcu;

    structnotifier_block *head;

};

通知链的核心结构:

struct notifier_block

{

    int(*notifier_call)(struct notifier_block *, unsigned long, void*);

    structnotifier_block *next;

    intpriority;

};
其中notifier_call是通知链要执行的函数指针,next用来连接其它的通知结构,priority是这个通知的优先级,同一条链上的notifier_block{}是按优先级排列的。内核代码中一般把通知链命名为xxx_chain,xxx_nofitier_chain这种形式的变量名。

3、举例应用:

NUM 1:build_chain.c。它的作用是自定义一个通知链表test_chain,然后再自定义两个函数分别向这个通知链中加入或删除节点,最后再定义一个函数通知这个test_chain链:

MODULE_LICENSE("GPL");

static RAW_NOTIFIER_HEAD(test_chain);

int register_test_notifier(struct notifier_block *nb)

{

  return raw_notifier_chain_register(&test_chain, nb);

}

EXPORT_SYMBOL(register_test_notifier);

int unregister_test_notifier(struct notifier_block *nb)

{

  return raw_notifier_chain_unregister(&test_chain,nb);

}

EXPORT_SYMBOL(unregister_test_notifier);

int test_notifier_call_chain(unsigned long val, void *v)

{

  returnraw_notifier_call_chain(&test_chain, val, v);

}

EXPORT_SYMBOL(test_notifier_call_chain);

static int __init init_notifier(void)

{

  printk("init_notifier\n");

  return 0;

}

static void __exit exit_notifier(void)

{

   printk("exit_notifier\n");

}

module_init(init_notifier);
module_exit(exit_notifier);

NUM 2: regchain.c。该代码的作用是将test_notifier1test_notifier2test_notifier3这三个节点加到之前定义的test_chain这个通知链表上,同时每个节点都注册了一个函数:

MODULE_LICENSE("GPL");

extern int register_test_notifier(struct notifier_block*);

extern int unregister_test_notifier(struct notifier_block*);

static int test_event1(struct notifier_block *this, unsigned longevent, void *ptr)

{

  printk("In Event 1: Event Number is %d\n",event);

  return 0;

}

static int test_event2(struct notifier_block *this, unsigned longevent, void *ptr)

{

  printk("In Event 2: Event Number is %d\n",event);

  return 0;

}

static int test_event3(struct notifier_block *this, unsigned longevent, void *ptr)

{

  printk("In Event 3: Event Number is %d\n",event);

  return 0;

}

static struct notifier_block test_notifier1 =

{

   .notifier_call = test_event1,

};

static struct notifier_block test_notifier2 =

{

   .notifier_call = test_event2,

};

static struct notifier_block test_notifier3 =

{

   .notifier_call = test_event3,

};

static int __init reg_notifier(void)

{

  int err;

  printk("Begin to register:\n");

 

  err =register_test_notifier(&test_notifier1);

  if (err)

  {

   printk("register test_notifier1 error\n");

    return-1;

  }

  printk("register test_notifier1completed\n");

  err =register_test_notifier(&test_notifier2);

  if (err)

  {

   printk("register test_notifier2 error\n");

    return-1;

  }

  printk("register test_notifier2completed\n");

  err =register_test_notifier(&test_notifier3);

  if (err)

  {

   printk("register test_notifier3 error\n");

    return-1;

  }

  printk("register test_notifier3completed\n");

 

  return err;

}

static void __exit unreg_notifier(void)

{

  printk("Begin to unregister\n");

 unregister_test_notifier(&test_notifier1);

 unregister_test_notifier(&test_notifier2);

 unregister_test_notifier(&test_notifier3);

  printk("Unregister finished\n");

}

module_init(reg_notifier);

module_exit(unreg_notifier);

NUM 3:notify.c。该代码的作用就是向test_chain通知链中发送消息,让链中的函数运行:

MODULE_LICENSE("GPL");

extern int test_notifier_call_chain(unsigned long val, void*v);

static int __init call_notifier(void)

{

  int err;

  printk("Begin to notify:\n");

 

 printk("----------------start----------------\n");

  err = test_notifier_call_chain(1, NULL);

 printk("----------end-----------\n");

  if (err)

         printk("notifier_call_chain error\n");

  return err;

}

static void __exit uncall_notifier(void)

{

    printk("End notify\n");

}

module_init(call_notifier);
module_exit(uncall_notifier);

refer:http://blog.chinaunix.net/uid-25871104-id-3086446.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: