首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是FD_SET,FD_CLR ...原子操作?

是FD_SET,FD_CLR ...原子操作?
EN

Stack Overflow用户
提问于 2012-02-27 05:54:05
回答 3查看 1.8K关注 0票数 1

我目前正在工作的应用程序是一个服务器,它将使用select()管理与客户端的连接,每次服务器接收到消息时,它都会打开一个新线程来读取套接字。在此期间,套接字的文件描述符将从集合中删除,并将在读取结束时添加。以下是代码的示例

代码语言:javascript
复制
struct s_handle {
 int sock;
 fd_set * rdfs;
};




int main(){
 ...
 fd_set rdfs;
 ...
 while(1){
 ....
  select(nb_fd,&rdfs,NULL,NULL,NULL)
  for_each(peer){
   if(FD_ISSET(peer->sock,&rdfs)){
     struct s_handle * h = malloc(sizeof(struct s_handle));
     h->sock = peer->sock;
     h->rdfs = &rdfs;
     FD_CLR(peer->sock,&rdfs);
     pthread_create(thread,NULL,handle,(void *)&h);
   }
  }
 ...
 }
 ...
 }

void* handle(void* argss){
 struct s_handle * temp = (struct s_handle *) argss;
 ...
 FD_SET(temp->sock,temp->rdfs);
}

FD_ISSET和FD_CLR是原子操作,还是需要用互斥锁锁定rdfs?

如果需要互斥,如何避免死锁?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-02-27 06:14:21

首先,你不应该创建那样的线程。创建线程是一个相当高的开销操作,应该仅在需要更多线程时使用,而不仅仅是因为您需要做更多工作。

是的,您确实需要使用互斥锁来保护FD_*函数。通常的解决方案是使用一个互斥锁,这个互斥锁只在执行FD_*操作的瞬间保持。在调用select之前,获取互斥锁,复制描述符集,然后释放互斥锁。

不过,一般来说,从读集合中删除套接字并不是一个好主意。将套接字放回读集合中不会改变稍后已经发生的select。您还需要弄清楚如何将调用select的线程从select中提取出来,以便在新的集合上进行操作。

您可能希望重新考虑您的I/O发现方法,并使用其中一个标准方法,而不是尝试使用您自己的方法。您正在进行丑陋的权衡,要么因为最近读取了某些套接字而select仍然被阻塞,而导致某些套接字不被侦听,要么在您完成对每个套接字的读取时必须重新执行select。这两种解决方案都不好。

一种更常见的模式是在读取套接字时将其保留在集合中,直到读取完所有套接字(但不一定处理其数据)后才返回select

票数 3
EN

Stack Overflow用户

发布于 2012-02-27 06:02:06

不能保证它们是正确的,而且您根本不应该依赖它。

fd_set通常使用普通的位图(int或类似的数组)来实现,而FD_*宏只是位操作操作。这些操作很少在任何比平台原生int更长的操作上是原子的(如果是这样的话)。

票数 1
EN

Stack Overflow用户

发布于 2012-02-27 06:03:41

FD_SETFD_ISSET等都是宏--我认为你不能指望它们是原子的。但是,我建议您重新考虑您的方法,而不是使用互斥锁;在需要读取时创建一个新线程,并从不同于使用其结果的线程调用select,这两种方法似乎都不太好。如果有一个特殊的原因,为什么您只需要使用单独的线程进行读取,而不是完全处理该连接,那么为什么不让它拥有自己的fd_set并调用select本身呢?

在重读这个问题时,我想说,如果您确实使用了现在的方法,那么您应该注意到,在每次调用select之前,需要重新构建读取的fd_set,并通过调用进行修改。因此,线程函数末尾的FD_SET无论如何都没有用,因为如果描述符没有准备好再次读取,那么它将在下一次select调用时从集合中删除。您需要在select调用之前在select线程中构建读取集--因此您需要另一种确定需要包含哪些套接字的方法。

您可以向s_handle结构添加一个忙标志,并使用互斥锁来保护它--然后在创建线程之前设置它,并在线程退出时将其清除。在select调用之前填充read fd_set时,需要为s_handle结构中未被标志标记为“忙”的每个对等体添加套接字。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9457536

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档