事件驱动中,信号量的处理

[复制链接]
1968|10
 楼主| Simon21ic 发表于 2015-8-23 16:05 | 显示全部楼层 |阅读模式
本帖最后由 Simon21ic 于 2015-8-23 16:12 编辑

之前说过,在一些特定的使用情况下,目标进程无法立即处理事件的时候,作为事件的缓冲。

那么在事件驱动下,如果使用信号量呢?
这里举例说明,如果要实现一个USB Hub的USB设备端驱动,端口上的变化,需要通过中断传输,发送notification给USB主机。发送notification的时候,会先写数据到相应的USB端点,然后等到数据发送完成,再看是否有其他notification需要发送。那么在等待USB发送完成的时候,就无法处理notification事件,所以就需要用到信号来缓冲。

第一种比较简单的方式,PT线程:
  1. vsf_err_t vsfusbd_thread(struct vsfsm_pt_t *pt, vsfsm_evt_t evt)
  2. {
  3.     struct vsfusbd_HUB_param_t *param =
  4.             (struct vsfusbd_HUB_param_t *)sm->user_data;
  5.     struct vsfusbd_device_t *device = param->device;
  6.     uint8_t notification;

  7.     vsfsm_pt_begin(pt);

  8.     vsfsm_sem_init(param->sem, 0, VSFUSBD_HUB_EVT_CHANGE);
  9.     while (1)
  10.     {
  11.         if (vsfsm_sem_pend(param->sem, sm))
  12.         {
  13.             vsfsm_pt_wfe(pt, VSFUSBD_HUB_EVT_CHANGE);
  14.         }

  15.         notification = 1;
  16.         device->drv->ep.write_IN_buffer(param->ep_in, notification, 1);
  17.         device->drv->ep.set_IN_count(param->ep_in, 1);
  18.         vsfsm_pt_wfe(pt, VSFUSBD_HUB_EVT_INOK);
  19.     }

  20.     vsfsm_pt_end(pt);
  21.     return VSFERR_NONE;
  22. }

这里,device->drv->ep是控制USB端点的接口,写入数据后,当发送完成后,会发送VSFUSBD_HUB_EVT_INOK事件。所以,写端口后,就可以直接简单等待这个事件就行。
vsfsm_sem_init用于初始化信号量,并且设置事件为VSFUSBD_HUB_EVT_CHANGE,主循环里,就试图获取信号量(vsfsm_sem_pend),如果得到的话返回0,就发送notification,否则返回非0,等待VSFUSBD_HUB_EVT_CHANGE事件。
其他代码发送了信号后,信号量发现有任务在等待,就发送相应的事件。
PT的代码简单明了,类似阻塞的代码方式,一看就明白。

用事件驱动的方式的话,就会相对麻烦一些,不过也很有意思:
  1. static struct vsfsm_state_t *
  2. vsfusbd_evt_handler(struct vsfsm_t *sm, vsfsm_evt_t evt)
  3. {
  4.     struct vsfusbd_HUB_param_t *param =
  5.             (struct vsfusbd_HUB_param_t *)sm->user_data;
  6.     struct vsfusbd_device_t *device = param->device;
  7.     uint8_t notification;

  8.     switch (evt)
  9.     {
  10.     case VSFSM_EVT_INIT:
  11.         vsfsm_sem_init(param->sem, 0, VSFUSBD_HUB_EVT_CHANGE);
  12.     case VSFUSBD_HUB_EVT_INOK:
  13.         if (vsfsm_sem_pend(param->sem, sm))
  14.         {
  15.             break;
  16.         }
  17.     case VSFUSBD_HUB_EVT_CHANGE:
  18.         notification = 1;
  19.         device->drv->ep.write_IN_buffer(param->ep_in, notification, 1);
  20.         device->drv->ep.set_IN_count(param->ep_in, 1);
  21.         break;
  22.     }
  23.     return NULL;
  24. }
INIT为初始化事件,初始化信号,然后马上等待信号,这里一定等待不到,所以之后有信号后,系统会发送VSFUSBD_HUB_EVT_CHANGE事件。
收到VSFUSBD_HUB_EVT_CHANGE事件后(信号量会把本线程从等待列表中去掉,除非再次调用sem_pend,否则不会收到CHANGE事件),写USB端口,之后USB模块会发送VSFUSBD_HUB_EVT_INOK事件
VSFUSBD_HUB_EVT_INOK事件里,继续等待信号量,是不是很简单?


 楼主| Simon21ic 发表于 2015-8-23 17:54 | 显示全部楼层
本帖最后由 Simon21ic 于 2015-8-23 18:08 编辑
yyy71cj 发表于 2015-8-23 16:57
在我的印象中……
        关于信号量这个概念,我一直以为这是一个不切实的叫法,也不知道到底是命名的问 ...
任何编程,不都只是一个方法吗?还能是什么?
C#里废除的话,那是不是指C和C++里有?
在ANSI C标准里有不?我去研究研究
 楼主| Simon21ic 发表于 2015-8-23 18:04 | 显示全部楼层
我在百度里搜索到很多C#利用信号量的**,信号量一般是操作系统提供的东西,不明白和C#有什么关系
李冬发 发表于 2015-8-24 02:18 | 显示全部楼层
keer_zu 发表于 2015-8-24 09:52 | 显示全部楼层
yyy71cj 发表于 2015-8-23 16:57
在我的印象中……
        关于信号量这个概念,我一直以为这是一个不切实的叫法,也不知道到底是命名的问 ...

信号量和语言有关系?这是知道面向对象语言里,类和类之间有类似消息这样的机制。
 楼主| Simon21ic 发表于 2015-8-24 10:14 | 显示全部楼层
yyy71cj 发表于 2015-8-24 07:07
信号量是早期多线程编程中的一个都有的概念和同步线程的方法,其实即使没有这个概念,我们编程时也会用到 ...

信号量确实和系统有关,和语言无关,C#里本来就没有信号量,.Net里的System.Threading里有Samephore。其他语言里,也没有信号量,信号量在系统的头文件里。或者,在你的构架里,信号量是一个变量,但这个都无法阻止信号量的存在。
我倒觉得以后这种构架化的开发方式会越来越流行,因为芯片资源越来越多
明年会有高资源ARM不到1美金,就市场角度而言,ARM还没到没落的时候
keer_zu 发表于 2015-8-24 10:32 | 显示全部楼层
Simon21ic 发表于 2015-8-24 10:14
信号量确实和系统有关,和语言无关,C#里本来就没有信号量,.Net里的System.Threading里有Samephore。其 ...

是的,信号量不是语言层次的东西。语言本身没有实体的概念,不关注实体之间的通信协调。所实现的“功能库”里面或许有类似概念,但是库不是语言本身的东西。
m564522634 发表于 2015-8-24 16:38 | 显示全部楼层
yyy71cj 发表于 2015-8-23 16:57
在我的印象中……
        关于信号量这个概念,我一直以为这是一个不切实的叫法,也不知道到底是命名的问 ...

这应该不是一个编程语言的概念吧,是操作系统中的一个概念。 只能过对事件的响应与处理分开的一种方法了。和linux的上下级中断一样的作用了。
keer_zu 发表于 2015-8-24 16:45 | 显示全部楼层
m564522634 发表于 2015-8-24 16:38
这应该不是一个编程语言的概念吧,是操作系统中的一个概念。 只能过对事件的响应与处理分开的一种方法了 ...

是共享资源的一种手段吧,和事件响应处理有什么关系?linux没有上下级中断的概念,是上半部,下半部,是完成不同响应速度和级别的。:L
m564522634 发表于 2015-8-24 16:49 | 显示全部楼层
keer_zu 发表于 2015-8-24 16:45
是共享资源的一种手段吧,和事件响应处理有什么关系?linux没有上下级中断的概念,是上半部,下半部,是 ...

想了下,你是对的, 谢谢指正学习了。
keer_zu 发表于 2015-8-24 17:11 | 显示全部楼层
m564522634 发表于 2015-8-24 16:49
想了下,你是对的, 谢谢指正学习了。

呵呵,不客气,相互学习。欢迎常来讨论。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:www.versaloon.com --- under construction

266

主题

2597

帖子

104

粉丝
快速回复 在线客服 返回列表 返回顶部