搜索
bottom↓
回复: 27

万能的论坛,Linux系统一次等待多个信号量怎么解决?

[复制链接]

出0入0汤圆

发表于 2017-2-11 18:28:09 | 显示全部楼层 |阅读模式
如题:请教论坛各位大神 ,linux下一次等待多个信号量怎么解决?
功能如同window下waitformultipleobjects()函数,一次就可以等待多个信号量。
在linux下多线程编程,linux 下sem_wait()一次只能等待一个信号量。

麻烦哪位高手指点一下 ,不胜感激。

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2017-2-12 11:35:02 | 显示全部楼层
不能嵌套吗?

出0入0汤圆

发表于 2017-2-12 12:14:10 | 显示全部楼层
用eventfd,然后用listen或epoll。

出0入0汤圆

 楼主| 发表于 2017-2-13 10:58:33 | 显示全部楼层
stdio 发表于 2017-2-12 12:14
用eventfd,然后用listen或epoll。

能否 给我发一个程序? 网上找的都是网络并发服务器 ,跟我想要实现的功能不一样。

我需要的功能是: 在主线程A阻塞等待,在线程B , 线程C,线程D 中都可以发信号来唤醒主线程A的阻塞 。

出0入0汤圆

发表于 2017-2-13 11:47:08 | 显示全部楼层
franki 发表于 2017-2-13 10:58
能否 给我发一个程序? 网上找的都是网络并发服务器 ,跟我想要实现的功能不一样。

我需要的功能是: 在 ...

用三个信号量不行吗?
  1. if(sem_wait(semA) || sem_wait(semB) || sem_wait(semC))
  2. {
  3.         /* code */
  4. }
复制代码

出300入477汤圆

发表于 2017-2-13 11:59:05 | 显示全部楼层
franki 发表于 2017-2-13 10:58
能否 给我发一个程序? 网上找的都是网络并发服务器 ,跟我想要实现的功能不一样。

我需要的功能是: 在 ...

那是你自己搞错了写法。
信号量是控制接收方的,不是控制发送方。
所以你等待唯一的一个信号量即可,
3个想唤醒它的都可以给它发送信号,哪个发送了都有效。

出0入0汤圆

发表于 2017-2-13 12:31:07 | 显示全部楼层
redroof 发表于 2017-2-13 11:59
那是你自己搞错了写法。
信号量是控制接收方的,不是控制发送方。
所以你等待唯一的一个信号量即可,

楼上正解,楼主的需求确实不需要那么多信号量。
1个信号量,三个线程发送,一个线程接收即可。

出0入0汤圆

 楼主| 发表于 2017-2-13 12:37:27 | 显示全部楼层
笑笑我笑了 发表于 2017-2-13 11:47
用三个信号量不行吗?

这个好 。谢谢指点  !

出300入477汤圆

发表于 2017-2-13 13:07:24 来自手机 | 显示全部楼层
笑笑我笑了 发表于 2017-2-13 11:47
用三个信号量不行吗?

sem_wait(semA) || sem_wait(semB) || sem_wait(semC)
这种写法在任何场合下都是错的。
不管你要任何要求,这样写都是错的!

出0入0汤圆

发表于 2017-2-13 13:25:46 | 显示全部楼层
sem_wait(semA) || sem_wait(semB) || sem_wait(semC)的写法显然是不行的,同意3楼看法

出0入0汤圆

发表于 2017-2-13 19:46:32 | 显示全部楼层
本帖最后由 笑笑我笑了 于 2017-2-13 19:51 编辑
redroof 发表于 2017-2-13 13:07
sem_wait(semA) || sem_wait(semB) || sem_wait(semC)
这种写法在任何场合下都是错的。
不管你要任何要求 ...

那这个思路还是可取的?改成

  1. if(sem_wait(A) == 0)
  2. {

  3. }

  4. if(sem_wait(B) == 0)
  5. {

  6. }

  7. if(sem_wait(C) == 0)
  8. {

  9. }
复制代码

出0入25汤圆

发表于 2017-2-13 20:39:12 来自手机 | 显示全部楼层
笑笑我笑了 发表于 2017-2-13 19:46
那这个思路还是可取的?改成

如果信号量A不被释放,线程永远被阻塞,后面两个if永远不会被执行。

出0入25汤圆

发表于 2017-2-13 20:42:16 来自手机 | 显示全部楼层
笑笑我笑了 发表于 2017-2-13 11:47
用三个信号量不行吗?

信号量C不被释放,即便A和B释放了线程也是被阻塞的。
阻塞,明白?为什么先是C不解释了。

出0入0汤圆

发表于 2017-2-13 20:50:01 | 显示全部楼层
lswood 发表于 2017-2-13 20:42
信号量C不被释放,即便A和B释放了线程也是被阻塞的。
阻塞,明白?为什么先是C不解释了。 ...

那把 sem_wait 换成 sem_timedwait 就没这个问题了吧。

出0入25汤圆

发表于 2017-2-13 20:54:15 | 显示全部楼层
笑笑我笑了 发表于 2017-2-13 20:50
那把 sem_wait 换成 sem_timedwait 就没这个问题了吧。

如果阻塞线程是要在超时前及时唤醒该如何呢?你这成为时间片轮流查询了。

出300入477汤圆

发表于 2017-2-14 08:32:32 来自手机 | 显示全部楼层
笑笑我笑了 发表于 2017-2-13 19:46
那这个思路还是可取的?改成

照样错。
除非你就是要求按顺序等待这几个信号量,依次做某些事。

出300入477汤圆

发表于 2017-2-14 08:35:30 来自手机 | 显示全部楼层
sem_wait(semA) || sem_wait(semB) || sem_wait(semC)跟只等待A完全一样。不带超时的等待总会成功,不成功就挂起自己直到成功为止

出0入0汤圆

发表于 2017-2-14 08:42:06 | 显示全部楼层
redroof 发表于 2017-2-14 08:35
sem_wait(semA) || sem_wait(semB) || sem_wait(semC)跟只等待A完全一样。不带超时的等待总会成功,不成功 ...

那正确的做法应该是什么样的呢?

出0入0汤圆

 楼主| 发表于 2017-2-14 09:13:11 | 显示全部楼层
vxworks 下有这个函数可以实现 :
eventReceive(events_Waitfor, EVENTS_WAIT_ANY,WAIT_FOREVER, &events_Recv);

出300入477汤圆

发表于 2017-2-14 09:15:30 | 显示全部楼层
笑笑我笑了 发表于 2017-2-14 08:42
那正确的做法应该是什么样的呢?

如果真的要并行等待多个信号量,而且随便哪个等到了都返回,那么Linux上正确的做法是eventfd加上epoll。

出300入477汤圆

发表于 2017-2-14 09:30:28 | 显示全部楼层
在windows上也很简单啊,直接一个waitformultipleobjects就可以了。各种核心对象都可以同样的等待。
而linux上对信号量的等待只能一次等待一个。可以等待多个的epoll或者select只能等待文件描述符,不能等待信号量。
因此你得用eventfd建立文件描述符来代替信号量,才能并行等待多个。

出0入0汤圆

 楼主| 发表于 2017-2-21 16:03:20 | 显示全部楼层
redroof 发表于 2017-2-14 09:30
在windows上也很简单啊,直接一个waitformultipleobjects就可以了。各种核心对象都可以同样的等待。
而linu ...

请问如何 “用eventfd建立文件描述符来代替信号量 ”,麻烦指点一下 !
不胜感激  !

出300入477汤圆

发表于 2017-2-21 21:05:44 | 显示全部楼层
franki 发表于 2017-2-21 16:03
请问如何 “用eventfd建立文件描述符来代替信号量 ”,麻烦指点一下 !
不胜感激  !  ...

搜索 eventfd  epoll 就知道了
语义就是正确的“并联”语义,并行等待多个描述符,任何一个有数据了都返回。

出0入0汤圆

发表于 2017-2-21 21:57:31 来自手机 | 显示全部楼层
redroof 发表于 2017-2-21 21:05
搜索 eventfd  epoll 就知道了
语义就是正确的“并联”语义,并行等待多个描述符,任何一个有数据了都返 ...

老大很牛啊,对linux也有研究

出0入0汤圆

发表于 2017-2-23 05:23:05 来自手机 | 显示全部楼层
参考下libuv的代码

出0入0汤圆

发表于 2017-2-23 18:37:50 来自手机 | 显示全部楼层
1个信号量就可以,如果需要知道哪个线程发送的,直接用消息队列

出0入0汤圆

 楼主| 发表于 2017-2-24 09:00:11 | 显示全部楼层
first_blood 发表于 2017-2-23 18:37
1个信号量就可以,如果需要知道哪个线程发送的,直接用消息队列

消息队列 是进程间通信 ,多线程里面好像没有这个 。

出300入477汤圆

发表于 2017-2-24 09:07:50 | 显示全部楼层
franki 发表于 2017-2-24 09:00
消息队列 是进程间通信 ,多线程里面好像没有这个 。

“线程之间”相当于是“进程之间”的特例而已。
任何可以用在进程间的通讯方式,在线程之间当然都是可以用的。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-25 15:23

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表