• 全部
...

Linux 下如何实现wait多个semaphore的函数,功能类似windows WaitForMultipleObject

xyf_1986 2009-06-03 11:02:54
最近在做系统移植,碰到了个个人觉得较麻烦的问题:我想通过一个wait函数来wait多个semaphore, 返回有信号的semaphore,但linux 找不到功能类似windows WaitForMultipleObject的函数。看到有人说,select函数可以,但查资料后,select不行。
之前我在网上找了很多资料,但一直也没有找到合适的解决方法,网上也有很多人遇到这个问题。
曾经碰到过这个问题的朋友们,麻烦指点下小弟,在此先谢谢啦
...全文
给本帖投票
999 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhangshu88 2011-03-30
  • 打赏
  • 举报
回复
13楼中 提到的 "Listing 13. Linux equivalent code using System V semaphores (wait until all semaphores are signaled) " 的这个例子实现了 WaitForMultipleObjects()的参数bWaitAll = TRUE 的情况,但我现在在从windows向linux移植的过程中发现 用Listing 13同样的方法(using System V semaphores )去实现WaitForMultipleObjects()的参数bWaitAll = FALSE 的情况比较困难,请问各位大侠,有没有什么好的实现方法,谢谢!
xyf_1986 2009-07-07
  • 打赏
  • 举报
回复
恩,谢谢大家,IMB上的我很早之前就找到过了,由于信号有很多,若每个信号都一个线程的话,那要启的线程太多了,所以,我没选择imb上面说的方法。采用了另一种事件触发的方法。若碰到相同问题的朋友可以给我发邮件yangfeixu@hotmail.com
xyf_1986 2009-07-07
  • 打赏
  • 举报
回复
我有1024个信号,难道得开1024个线程?这是我找的IBM上的一篇文章,地址为
http://www.ibm.com/developerworks/linux/library/l-ipc2lin3.html

Waiting on an array

WaitForMultipleObjects() is the simplest function available in this type. This function takes an array on one or more synchronized objects as input and blocks the calling thread until any of the following criteria is met:

Either any one or all of the specified objects are in the signaled state.
The timeout interval elapses.
DWORD WaitForMultipleObjects(
DWORD nCount,
const HANDLE* lpHandles,
BOOL bWaitAll,
DWORD dwMilliseconds
)



In this code:

nCount is the number of object handles in the array pointed to by lpHandles.
lpHandles is a pointer to array of object handles.
bWaitAll is a flag and if this parameter is TRUE, the function waits until all the objects are in signaled state.
dwMilliseconds is the timeout value in milliseconds.
In Linux, the same functionality can be achieved by using additional logic in the code. In the context of threads, POSIX semaphores are used and in the context of processes, System V semaphores are used. In Windows, if the bWaitAll flag is FALSE, the thread/process is released if any one of the synchronization objects are signaled. Linux does not provide this functionality. This logic needs to be handled in the application logic.

Examples

Following are examples for multiple objects wait functions.


Listing 9. Windows example for any single object to be signaled
HANDLE hEvents[2];
DWORD i, dwRetCode;

// Create two event objects.

for (i = 0; i < 2; i++)
{
hEvents[i] = CreateEvent(
NULL, // no security attributes
FALSE, // auto-reset event object
FALSE, // initial state is nonsignaled
NULL); // unnamed object

}

// The creating thread waits for other threads or processes
// to signal the event objects.

dwRetCode = WaitForMultipleObjects(
2, // number of objects in array
hEvents, // array of objects
FALSE, // wait for any
INFINITE); // indefinite wait

// Return value indicates which event is signaled.

switch (dwEvent)
{
// hEvent[0] was signaled.
case WAIT_OBJECT_0 + 0:
// Perform tasks required by this event.
break;

// hEvent[1] was signaled.
case WAIT_OBJECT_0 + 1:
// Perform tasks required by this event.
break;

// Return value is invalid.
default:
// probe for error
}



Listing 10. Linux equivalent code using POSIX
// Semaphore
sem_t semOne ;
sem_t semTwo ;
sem_t semMain ;

// Main thread
sem_init(semOne,0,0) ;
sem_init(semTwo,0,0) ;
sem_init(semMain,0,0) ;

// create 2 threads each one waits on one semaphore
// if signaled signals the main semaphore

sem_wait(&semMain);


// Thread 1
sem_wait(&semOne);
sem_post(&semMain);


// Thread 2
sem_wait(&semTwo);
sem_post(&semMain);



Listing 11. Windows example for all objects to be signaled
HANDLE hEvents[2];
DWORD i, dwRetCode;

// Create two event objects.

for (i = 0; i < 2; i++)
{
hEvents[i] = CreateEvent(
NULL, // no security attributes
FALSE, // auto-reset event object
FALSE, // initial state is nonsignaled
NULL); // unnamed object

}

// The creating thread waits for other threads or processes
// to signal the event objects.

dwRetCode = WaitForMultipleObjects(
2, // number of objects in array
hEvents, // array of objects
TRUE, // wait for both the objects to be signaled
INFINITE); // indefinite wait

// Return value indicates which event is signaled.

switch (dwEvent)
{
// hEvent[0] and hEvent[1] were signaled.
case WAIT_OBJECT_0 :
// Perform tasks required by this event.

break;

// Return value is invalid.
default:
// probe for error
}



Listing 12. Linux equivalent code using POSIX
// Semaphore
sem_t semOne ;
sem_t semTwo ;
sem_t semMain ;
pthread_mutex_t mutMain = PTHREAD_MUTEX_INITIALIZER;

// Main thread
sem_init(semOne,0,0) ;
sem_init(semTwo,0,0) ;
sem_init(semMain,0,0) ;

// create 2 threads each one waits on one semaphore
// if signaled signals the main semaphore

sem_wait(&semMain);


// Thread 1
sem_wait(&semOne);

// lock the Mutex
pthread_mutex_lock(&mutMain);
count ++;
if(count == 2) {
// semaphore semTwo is already signaled
// so post the main semaphore
sem_post(&semMain);
}
pthread_mutex_unlock(&mutMain);


// Thread 2
sem_wait(&semTwo);
// lock the Mutex
pthread_mutex_lock(&mutMain);
count ++;
if(count == 2) {
// semaphore semOne is already signaled
// so post the main semaphore
sem_post(&semMain);
}
pthread_mutex_unlock(&mutMain);



Listing 13. Linux equivalent code using System V semaphores (wait until all semaphores are signaled)
// Main thread
int key = 0x20; // Semaphore key

// Thread 1
struct sembuf operation[2] ;

// Create 2 semaphores
semid = semget(key, 2, 0666 | IPC_CREAT);


operation[0].sem_op = -1; // Wait on first resource
operation[0].sem_num = 0;
operation[0].sem_flg = SEM_UNDO;

operation[0].sem_op = -1; // Wait on the second resource
operation[0].sem_num = 1;
operation[0].sem_flg = SEM_UNDO;

// Wait on both the semaphores
// Note : thread is suspended until both the semaphores are released.
semop(semid, operation, 2);

// thread is released
// delete the semaphore
semctl(semid, 0, IPC_RMID , 0)


// Thread 2
struct sembuf operation[1] ;

// open semaphore
mysemid = semget(key, 2, 0);

operation[0].sem_op = 1; // Release on the second resource
operation[0].sem_num = 1;
operation[0].sem_flg = SEM_UNDO;

//Release semaphore 2
semop(semid, operation, 1);

// Thread 3
struct sembuf operation[1] ;

// open semaphore
mysemid = semget(key, 2, 0);

operation[0].sem_op = 1; // Release on the first resource
operation[0].sem_num = 0;
operation[0].sem_flg = SEM_UNDO;

//Release semaphore 1
semop(semid, operation, 1);

daniel_yao 2009-06-04
  • 打赏
  • 举报
回复
原理和7楼的说的一样,多开几个线程等待
daniel_yao 2009-06-04
  • 打赏
  • 举报
回复
给你个网址,上面说的很清楚 我是按那上面的做的
http://www.ibm.com/developerworks/linux/library/l-ipc2lin3.html
http://www.ibm.com/developerworks/linux/library/l-ipc2lin2.html
http://www.ibm.com/developerworks/linux/library/l-ipc2lin3.html
mymtom 2009-06-04
  • 打赏
  • 举报
回复
其实就是多路复用的原理。
mymtom 2009-06-04
  • 打赏
  • 举报
回复
可以试试线程嘛,起n个线程,等sem,然后通知调用线程。
threeleafzerg007 2009-06-04
  • 打赏
  • 举报
回复
赞楼上的给出的链接。。。

fetag的解决方案 看不懂
独孤过儿 2009-06-04
  • 打赏
  • 举报
回复
典型的IO复用啊!

调用select()以后,会等待一组信号,根据不同的信号,做不同的处理。当没有信号产生时,阻塞在select()上
ITfat 2009-06-03
  • 打赏
  • 举报
回复
select阻塞的时候如果没有信号,它会阻塞在那里,但好像是不会耗费系统资源。这时候系统可以做其他的事情的。
xyf_1986 2009-06-03
  • 打赏
  • 举报
回复
不好意思,还有一个要求,就是所有semaphore都没信号时,将阻塞;若通过自己写一个my_wait的话,在所有semaphore没信号的时候,将进入死循环,一直在循环判断各个semaphore的状态,开销太大了
  • 打赏
  • 举报
回复
[Quote=引用楼主 xyf_1986 的帖子:]
最近在做系统移植,碰到了个个人觉得较麻烦的问题:我想通过一个wait函数来wait多个semaphore, 返回有信号的semaphore,但linux 找不到功能类似windows WaitForMultipleObject的函数。看到有人说,select函数可以,但查资料后,select不行。
之前我在网上找了很多资料,但一直也没有找到合适的解决方法,网上也有很多人遇到这个问题。
曾经碰到过这个问题的朋友们,麻烦指点下小弟,在此先谢谢啦
[/Quote]

写个my_wait函数,里面用select来分别wait不同的信号量,有响应就返回给my_wait。
这样不可以吗?
xyf_1986 2009-06-03
  • 打赏
  • 举报
回复
小弟在线等待
xyf_1986 2009-06-03
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 ITfat 的回复:]
select阻塞的时候如果没有信号,它会阻塞在那里,但好像是不会耗费系统资源。这时候系统可以做其他的事情的。
[/Quote]
是不会耗用系统资源,但有一个问题是
fd_set()的第一个参数是int类型的,所以select不能用来select sem_t类型的semaphore吧
xyf_1986 2009-06-03
  • 打赏
  • 举报
回复
select能用sem_t 类型的信号量做参数

23,216

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧

手机看
关注公众号

关注公众号

客服 返回
顶部