Linux Select之坑
最近在写一个demo程序,调用select()来监听socket状态,流程如下:
r_set 初始化
timeout 初始化3秒超时
loop{
select(ntfs, &r_set, null, null, &timeout)
}
然后我惊奇的发现当对端发送消息时select()只会触发一次,当下一次再有消息传递过来的时候不会被触发,后来在网上搜索了一下说是要每一次循环都要初始化一次r_set,就可以完成多次触发了:
timeout 初始化3秒超时
loop{
r_set 初始化
select(ntfs, &r_set, null, null, &timeout)
}
同时超时也只有在第一次循环阻塞三秒,之后的循环完全不会阻塞,我打日志调试发现在第一次阻塞超时之后timeout 重置为 0... ...
loop{
r_set 初始化
timeout 初始化3秒超时
select(ntfs, &r_set, null, null, &timeout)
}
这才是正确姿势,但是我在网上看到很多例子并没有重复初始化timeout,难道是我用了假select()?本着实事求是的原则我查看了一下man文档,上面写了这么一句话:
On Linux, select() modifies timeout to reflect the amount of time not slept; most other implementations do not do this. (POSIX.1 permits either behavior.) This causes problems both when Linux code which reads timeout is ported to other operating systems, and when code is ported to Linux that reuses a struct timeval for multiple select()s in a loop without reinitializing it. Consider timeout to be undefined after select() returns.
好吧,确实很任性,但作用类似的C library 中的pselect()就不用这么做:
C library/kernel differences
The pselect() interface described in this page is implemented by glibc. The underlying Linux system call is named pselect6(). This system call has somewhat different behavior from the glibc
wrapper function.
The Linux pselect6() system call modifies its timeout argument. However, the glibc wrapper function hides this behavior by using a local variable for the timeout argument that is passed to
the system call. Thus, the glibc pselect() function does not modify its timeout argument; this is the behavior required by POSIX.1-2001.
The final argument of the pselect6() system call is not a sigset_t * pointer, but is instead a structure of the form:
struct {
const sigset_t *ss; /* Pointer to signal set */
size_t ss_len; /* Size (in bytes) of object pointed
to by 'ss' */
};
This allows the system call to obtain both a pointer to the signal set and its size, while allowing for the fact that most architectures support a maximum of 6 arguments to a system call
它的意思是,pselect()在传入时间参数的时候会付给一个参数temp,然后把temp传进去,这样就不会修改timeout参数了。
ps:
If a file descriptor being monitored by select() is closed in another thread, the result is unspecified. On some UNIX systems, select() unblocks and returns, with an indication that the file
descriptor is ready (a subsequent I/O operation will likely fail with an error, unless another the file descriptor reopened between the time select() returned and the I/O operations was per‐
formed). On Linux (and some other systems), closing the file descriptor in another thread has no effect on select(). In summary, any application that relies on a particular behavior in this
scenario must be considered buggy.
Linux Select之坑的更多相关文章
- linux select 与 阻塞( blocking ) 及非阻塞 (non blocking)实现io多路复用的示例
除了自己实现之外,还有个c语言写的基于事件的开源网络库:libevent http://www.cnblogs.com/Anker/p/3265058.html 最简单的select示例: #incl ...
- linux—select具体解释
linux—select具体解释 select系统调用时用来让我们的程序监视多个文件句柄的状态变化的.程序会停在select这里等待,直到被监视的文件句柄有一个或多个发生了状态改变. 关于文件句柄,事 ...
- linux select 与 阻塞( blocking ) 及非阻塞 (non blocking)实现io多路复用的示例【转】
转自:https://www.cnblogs.com/welhzh/p/4950341.html 除了自己实现之外,还有个c语言写的基于事件的开源网络库:libevent http://www.cnb ...
- linux select函数详解
linux select函数详解 在Linux中,我们可以使用select函数实现I/O端口的复用,传递给 select函数的参数会告诉内核: •我们所关心的文件描述符 •对每个描述符,我们所关心的状 ...
- Linux select 机制深入分析
Linux select 机制深入分析 作为IO复用的实现方式.select是提高了抽象和batch处理的级别,不是传统方式那样堵塞在真正IO读写的系统调用上.而是堵塞在sele ...
- Linux select TCP并发服务器与客户端编程
介绍:运行在ubuntu linux系统,需要先打开一个终端运行服务端代码,这时,可以打开多个终端同时运行多个客户端代码(注意客户端数目要小于MAX_FD);在客户端输入数据后回车,可以看见服务器收到 ...
- Linux select I/O 复用
用途 在处理多个socket套接字的时候,会很自然的遇到一个问题:某个套接字什么时候可读?什么时候可写?哪些套接字是需要关闭的?我们可以回忆一下,一般我们在最开始编写socket程序的时候,send, ...
- Linux使用踩坑记
Ubuntu安装坑: 1.对于新手第一次安装ubuntu,特殊情况会出现因为分辨率问题导致安装界面不全,无法进行下一步操作. 解决方案:使用alt+鼠标左键拖动屏幕Linux文件名乱码问题: 2.因为 ...
- 从U盘安装linux(前人踩坑后人乘凉)
今天踩了一个大坑,网上的教程从u盘安装linux少了一个关键步骤导致我挣扎了两个小时 废话不多说,开始需要准备一些东西 1.从官网下载一个Ubuntu 10.04的镜像 2.一个大于等于1G的支持启动 ...
随机推荐
- 关于Mysql下使用Dapper QueryFirstOrDefault的问题
1.环境 MySql:5.7.20 Dapper:1.50.2 .Net:4.5 2.遇到的问题 在开发中我发现,使用Dapper查询数据时,第一次查询正确,第二次查询就差不出来,或者直接修改数据库后 ...
- Java爬虫——网易云热评爬取
爬取目标网址 : http://music.163.com/#/song?id=409649818 需要爬取信息 : 网易云top13热评 使用之前的 HttpURLConnection 获取 ...
- JAVA8之lambda表达式具体解释,及stream中的lambda使用
前言: 本人也是学习lambda不久,可能有些地方描写叙述有误,还请大家谅解及指正! lambda表达式具体解释 一.问题 1.什么是lambda表达式? 2.lambda表达式用来干什么的? 3.l ...
- 【百度之星2014~初赛(第二轮)解题报告】JZP Set
声明 笔者近期意外的发现 笔者的个人站点http://tiankonguse.com/ 的非常多文章被其他站点转载,可是转载时未声明文章来源或參考自 http://tiankonguse.com/ 站 ...
- Android学习笔记(27):日历视图Calendar
日历视图CalendarView可用于显示和选择日期. 能够调用setOnDateChangedListener()方法绑定事件监听器. 经常使用XML属性和相关方法: XML属性 相关方法 说明 a ...
- 使用<jsp:include>,不想写死URL,动态生成URL的解决的方法
JSP中文件包括有2种方式,静态包括和动态包括. 静态包括使用<%@ include file="" %>.动态包括使用<jsp:include page=&qu ...
- JAVA入门[14]-Spring MVC AOP
一.基本概念 1.AOP简介 DI能够让相互协作的软件组件保持松散耦合:而面向切面编程(aspect-oriented programming,AOP)允许你把遍布应用各处的功能分离出来形成可重用的组 ...
- 用js把图片做的富有动态感,并对以后需要用着的属性进行封装
首先我们先要导入几张图片(我已导入完毕): : 好,我们先写一个 <div ></div>, 定义一个 class="contair", 在这<div ...
- String类为什么要用final修饰(面试回答)
String是所有语言中最常用的一个类.我们知道在Java中,String是不可变的.final的.Java在运行时也保存了一个字符串池(String pool),这使得String成为了一个特别的类 ...
- .NET 构造Class返回多个json值
上次总结使用DataTable返回多个值,后来看到一个小哥的返回方式和我的有所不同,便留意了一下.原来他构造一个Class,而我构造的是一个Table. 首先说说两者的区别:拿student举例,st ...