多线程每个线程selecet为什么不会出现类似“惊群”现象?

kz3333 2005-12-09 08:51:25
有多个多线程,每个线程都selecet,为什么当一个socket可读的时候,不会唤醒每个线程里的select


for(int i = 0; i <THREAD_NUMBER; i++)
{
pthread_create(&pid[i], NULL, &start, NULL);
// sleep(1);
}

void* start(void* pParam)
{


int fd = socket(PF_INET, SOCK_STREAM, 0);
sockaddr_in sa_in;
memset(&sa_in, 0, sizeof(sa_in));
sa_in.sin_family = AF_INET;
sa_in.sin_port = htons(3007);
sa_in.sin_addr.s_addr = inet_addr(ipaddr);
int ret = connect(fd, (struct sockaddr*)&sa_in, sizeof(sa_in));

//往echo server写,在把“abc”从server读回来
write(fd,"abc",3)

//1024一般为linux最大socket值,就是本进程所有的socket都select到了
if (select(1024,&readfds, NULL, NULL, &tv) > 0)




}

上面是一些骨架代码,,奇怪的是线程1的echo只会被线程1的select到,为什么不会被“线程2”select到?当一个socket可读的时候,它怎么知道要唤醒正在select它的线程。它应该只能通知到socket所在的进程吧。
...全文
327 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
newbiestar 2005-12-28
  • 打赏
  • 举报
回复
又看了一下,并且试了一下,就算是超过256的fd,也会被select检查……

还有,修改fd_set数量的宏叫做FD_SETSIZE
newbiestar 2005-12-28
  • 打赏
  • 举报
回复
是吗?看我的这段代码

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <pthread.h>

#define WRITE_STATIC_TEXT(fd, text) (write((fd), (text), (sizeof(text))))
void* thr_routine(void* args)
{
fd_set myfd;
FD_ZERO(&myfd);

FD_SET(STDIN_FILENO, &myfd);
if (select(STDIN_FILENO+1, &myfd, 0, 0, 0) < 0)
{
perror("pthreaded_select: thr_routine: select:");
}
if (FD_ISSET(STDIN_FILENO, &myfd))
{
WRITE_STATIC_TEXT(STDOUT_FILENO, "select stdin in the thread routine\n");
}
return 0;
}

int main(void)
{
fd_set myfd;
pthread_t thr;
pthread_create(&thr, 0, thr_routine, 0);

FD_ZERO(&myfd);
FD_SET(STDIN_FILENO, &myfd);
if (select(STDIN_FILENO+1, &myfd, 0, 0, 0) < 0)
{
perror("pthread_select: main: select:");
}
if (FD_ISSET(STDIN_FILENO, &myfd))
{
WRITE_STATIC_TEXT(STDOUT_FILENO, "select stdin in the main routine\n");
}
sleep(2);
return 0;
}

的确会造成惊群的现象,至少FreeBSD上面的实现这样的。编译以后如果用重定向/管道给定输出的话,那么的确会有两个select的输出。

不知道是不是和你的意思一致?

还有,那个1024是错误的。因为可以通过修改某个宏修改这个行为(还有一些OS上面根本就达不到1024……譬如FreeBSD的manual里面就说了由于历史原因只有256个fd会被检测……)
kz3333 2005-12-26
  • 打赏
  • 举报
回复
已经解决,跟具体代码有关

to  hoyt(hoyt(欢迎访问 www.linuxc.net))
select 会唤醒多个进程(当这些进程为同一个父进程派生)

to lcl118(Lore-beggar)
1 socket非常象命名管道,遵照典型的生产者/消费者模型设计。上述情况是由于线程1排在“睡眠队列”的头上,如果线程1收到一个echo后,下一个echo应该是线程2收到,依次循环....
//错误,不是依次的,可以看steven网络编程1
2 socket是一种进程通信机制,可以在不同进程间传递信息。因此,“它应该只能通知到socket所在的进程吧”是错误的。
//错误,是可以在不同进程间传递信息,但我说的不是这个问题阿,是由一个进程创建的socket不可以给没有亲缘关系的进程使用
hoyt 2005-12-19
  • 打赏
  • 举报
回复
内核里面已经确保了select只会唤醒一个进程(线程)

欢迎访问linux下C语言编程网站 www.linuxc.net
lirun 2005-12-18
  • 打赏
  • 举报
回复
你把每个fd都往readfds里FD_SET了没有?
bekars 2005-12-12
  • 打赏
  • 举报
回复
//1024一般为linux最大socket值,就是本进程所有的socket都select到了

这句话不懂,有问题吧

我查查资料先
lcl118 2005-12-12
  • 打赏
  • 举报
回复
1 socket非常象命名管道,遵照典型的生产者/消费者模型设计。上述情况是由于线程1排在“睡眠队列”的头上,如果线程1收到一个echo后,下一个echo应该是线程2收到,依次循环....
2 socket是一种进程通信机制,可以在不同进程间传递信息。因此,“它应该只能通知到socket所在的进程吧”是错误的。
loserking 2005-12-11
  • 打赏
  • 举报
回复
哦,对。没看清楼主的意图。

mark
linux_DD 2005-12-11
  • 打赏
  • 举报
回复
学习
kz3333 2005-12-11
  • 打赏
  • 举报
回复
to loserking(刻舟求剑)

不是,所有线程是共享的本进程的所有client port所对应的fd
事实上是,线程select同一组东西
loserking 2005-12-09
  • 打赏
  • 举报
回复
这有什么奇怪。不止是socket server需要端口,client在connect的时候也是要打开端口的,不过这个端口是随机的。你的每个线程都在select不同的client port所对应的fd,当然是各得其所了。

23,127

社区成员

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

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