franki 发表于 2017-2-11 18:28:09

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

如题:请教论坛各位大神 ,linux下一次等待多个信号量怎么解决?
功能如同window下waitformultipleobjects()函数,一次就可以等待多个信号量。
在linux下多线程编程,linux 下sem_wait()一次只能等待一个信号量。

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

GunGun 发表于 2017-2-12 11:35:02

不能嵌套吗?

stdio 发表于 2017-2-12 12:14:10

用eventfd,然后用listen或epoll。

franki 发表于 2017-2-13 10:58:33

stdio 发表于 2017-2-12 12:14
用eventfd,然后用listen或epoll。

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

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

笑笑我笑了 发表于 2017-2-13 11:47:08

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

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

用三个信号量不行吗?
if(sem_wait(semA) || sem_wait(semB) || sem_wait(semC))
{
        /* code */
}

redroof 发表于 2017-2-13 11:59:05

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

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

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

luobote55 发表于 2017-2-13 12:31:07

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


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

franki 发表于 2017-2-13 12:37:27

笑笑我笑了 发表于 2017-2-13 11:47
用三个信号量不行吗?

这个好 。谢谢指点!
{:victory:}

redroof 发表于 2017-2-13 13:07:24

笑笑我笑了 发表于 2017-2-13 11:47
用三个信号量不行吗?

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

jameszxj 发表于 2017-2-13 13:25:46

sem_wait(semA) || sem_wait(semB) || sem_wait(semC)的写法显然是不行的,同意3楼看法

笑笑我笑了 发表于 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)
这种写法在任何场合下都是错的。
不管你要任何要求 ...
那这个思路还是可取的?改成

if(sem_wait(A) == 0)
{

}

if(sem_wait(B) == 0)
{

}

if(sem_wait(C) == 0)
{

}

lswood 发表于 2017-2-13 20:39:12

笑笑我笑了 发表于 2017-2-13 19:46
那这个思路还是可取的?改成

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

lswood 发表于 2017-2-13 20:42:16

笑笑我笑了 发表于 2017-2-13 11:47
用三个信号量不行吗?

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

笑笑我笑了 发表于 2017-2-13 20:50:01

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

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

lswood 发表于 2017-2-13 20:54:15

笑笑我笑了 发表于 2017-2-13 20:50
那把 sem_wait 换成 sem_timedwait 就没这个问题了吧。

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

redroof 发表于 2017-2-14 08:32:32

笑笑我笑了 发表于 2017-2-13 19:46
那这个思路还是可取的?改成

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

redroof 发表于 2017-2-14 08:35:30

sem_wait(semA) || sem_wait(semB) || sem_wait(semC)跟只等待A完全一样。不带超时的等待总会成功,不成功就挂起自己直到成功为止

笑笑我笑了 发表于 2017-2-14 08:42:06

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

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

franki 发表于 2017-2-14 09:13:11

vxworks 下有这个函数可以实现 :
eventReceive(events_Waitfor, EVENTS_WAIT_ANY,WAIT_FOREVER, &events_Recv);

redroof 发表于 2017-2-14 09:15:30

笑笑我笑了 发表于 2017-2-14 08:42
那正确的做法应该是什么样的呢?

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

redroof 发表于 2017-2-14 09:30:28

在windows上也很简单啊,直接一个waitformultipleobjects就可以了。各种核心对象都可以同样的等待。
而linux上对信号量的等待只能一次等待一个。可以等待多个的epoll或者select只能等待文件描述符,不能等待信号量。
因此你得用eventfd建立文件描述符来代替信号量,才能并行等待多个。

franki 发表于 2017-2-21 16:03:20

redroof 发表于 2017-2-14 09:30
在windows上也很简单啊,直接一个waitformultipleobjects就可以了。各种核心对象都可以同样的等待。
而linu ...

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

redroof 发表于 2017-2-21 21:05:44

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

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

myxiaonia 发表于 2017-2-21 21:57:31

redroof 发表于 2017-2-21 21:05
搜索 eventfdepoll 就知道了
语义就是正确的“并联”语义,并行等待多个描述符,任何一个有数据了都返 ...

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

qiushui_007 发表于 2017-2-23 05:23:05

参考下libuv的代码

first_blood 发表于 2017-2-23 18:37:50

1个信号量就可以,如果需要知道哪个线程发送的,直接用消息队列

franki 发表于 2017-2-24 09:00:11

first_blood 发表于 2017-2-23 18:37
1个信号量就可以,如果需要知道哪个线程发送的,直接用消息队列

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

redroof 发表于 2017-2-24 09:07:50

franki 发表于 2017-2-24 09:00
消息队列 是进程间通信 ,多线程里面好像没有这个 。

“线程之间”相当于是“进程之间”的特例而已。
任何可以用在进程间的通讯方式,在线程之间当然都是可以用的。
页: [1]
查看完整版本: 万能的论坛,Linux系统一次等待多个信号量怎么解决?