- 求职 : 系统工程师等
- 论坛徽章:
- 5
|
本帖最后由 qxhgd 于 2014-05-06 10:37 编辑
开发中使用tcpdump的时候,遇到过select的副作用引起的故障。
select的原型:- int select(int nfds, fd_set *rdfds, fd_set *wtfds, fd_set *exfds, struct timeval *timeout)
复制代码 不同系统上的实现:
POSIX.1标准是允许在实现中修改timeval的值的。
FreeBSD、Mac OS X、Solaris里一般维持不变。
Linux的实现中,几乎一定要被修改的只要配了超时时间,最终或者被修改为0或者被修改为剩余时间。
开始是每隔一定时间发消息出去,但是间隔在调用select之后,被修改导致出现问题。
附:Linux上的select的实现分析:- SYSCALL_DEFINE5(select)
- {
- if(tvp) //如果配置了超时时间,select最后一个参数非NULL的情况
- {
- endtime=xxx; //修改endtime,有点乱,主要是通过timespec_add_safe实现的。
- }
- ret = core_sys_select(n, inp, outp, exp, to);//真正实现超时的地方
- ret = poll_select_copy_remaining(&end_time, tvp, 1, ret);//注意这个1
-
- return ret;
- }
- static int poll_select_copy_remaining(struct timespec *end_time, void __user *p,
- int timeval, int ret)
- {
- if (!end_time->tv_sec && !end_time->tv_nsec) //如果前面tvp为Null,那么endtime没被赋值,值未定,这里可能就有问题了。
- return ret;
- ktime_get_ts(&rts); //获取当前时间
- rts = timespec_sub(*end_time, rts); //计算剩余时间
- if (rts.tv_sec < 0) //如果为负说明已经超时
- rts.tv_sec = rts.tv_nsec = 0; //清0
- if (timeval) { //select系统调用中,timeval为1
- rtv.tv_sec = rts.tv_sec; //存的是剩余时间(以endtime为参照物),可能为0,
- rtv.tv_usec = rts.tv_nsec / NSEC_PER_USEC;
- if (!copy_to_user(p, &rtv, sizeof(rtv))) //将剩余时间还给用户态
- return ret;
- }
- }
复制代码 |
|