select 出错! errno:22(EINVAL)

简介: select 出错! errno:22(EINVAL)

errno = 0; 很多文章都抄来抄去,哔哔了半天手动清零errno,也没有说怎么清零errno错误。实际上就这一句话。若你不执行这一句话等个几个小时,系统才可能给你清零,可不是等几分钟。有时间一个最简单操作能难道英雄汉。实践是检验真理的唯一标准。


当linx函数出现错误时,常常返回一个负值,而且整型变量errno通常被设置为含有附加信息的一个值。例如,open函数如果成功执行则返回一个非负文件描述符,如出错则返回-1.在open出错时,有大约15种不同的errno值(文件不存在、权限问题等)。某些函数并不返回负值而是使用另一种约定。例如,返回一个指向对象指针的大多数函数,在出错时,将返回一个NULL指针。

文件<errno.h>中定义了符号errno以及可以赋予的各个常量,这些常量都以字符E开头。例如,若errno等于常量EACESS,这表示产生了权限问题(例如,没有打开所要求文件的足够权限)。

POSIX和ISO C将errno定义为这一一个符号,它扩展成为一个可以修改的整型左值。这可以是包含出错编号的一个整数,或是一个返回出错编号指针的函数。以前使用的定义是:

extern int errno;

但是在支持线程的环境中,多个线程共享进程地址空间,每个线程都有属于自己的局部errno以避免一个线程干扰另一个线程。

对于errno应当知道两条规则。第一条规则:如果没有出错,则其值不会被一个例程清除。因此,仅当函数返回指明出错时,才检验其值。第二条:任何一个函数都不会将errno值设置为0,在<errno.h>中定义的所有常量都不为0。
C标准定义了两个函数,它们帮助打印出错信息。

#include <string.h>

char *strerror(int errnum);


此函数将errnum(它通常就是errno值)映射到一个出错信息字符串,并且返回此字符串的指针。

perror函数基于errno的当前值,在标准错误上产生一条出错信息,

#include <stdio.h>


void perror(const char *msg);


它首先输出由msg指向的字符串,然后是一个冒号,一个空格,接着是对应于errno值的出错信息,最后是一个换行符。


出错恢复

可与将<errno.h>中定义的各种出错分出致命性的和非致命性的两类。对于致命性的错误,无法执行恢复动作,最多只能在用户屏幕上打印一条出错信息,或者将一条出错信息写到日志文件中,然后终止。而对于非致命性错误,有课可以较为妥善的处理。大多数非致命性错误在本质上是暂时的,例如资源短缺,当系统中活动较少时,这种出错很可能就不会发生。

与资源相关的非致命性错误包括EAGAIN、ENFILE、ENOBUFS、ENOLCK等,当EBUSY指明共享资源正在使用时,也可以将其作为非致命性错误处理。

对于资源相关的非致命性错误,一般恢复动作是延迟一些时间,然后进行错误清零(errno = 0; 很多文章都抄来抄去,哔哔了半天手动清零errno,也没有说怎么清零errno错误。实际上就这一句话。若你不执行这一句话等个几个小时,系统才可能给你清零,可不是等几分钟。有时间一个最简单操作能难道英雄汉。实践检验真理的唯一标准。)再进行尝试。这种技术可以应用于其他情况。例如,当一个出错表明网络连接不再起作用,那么应用程序可以在短时间延迟后重建该连接,某些应用使用指数补偿算法,在每次重复中等待更多的时间。

iOS系统也有这个问题。

我用select和管道函数写的一个随时可变时长定时器就遇到这个问题。

            tv.tv_sec = (__darwin_time_t)(NSUIntegerMax);
            tv.tv_usec = (__darwin_suseconds_t)self.customTimerWaitTimeUsecInterval;
            
            self.customTimerSelectTime = [[NSDate date] timeIntervalSince1970];
//            NSLog(@"select befor now time:%lld", self.customTimerSelectTime);
            if((self.fdCustomTimerModifyWaitTimeReadPipe <= 0) || (self.fdCustomTimerModifyWaitTimeWritePipe <= 0))
            {
                //守护线程管道已经关闭
                NSLog(@"关闭select超时的线程, Thread Sno: %@\n", [self getSocketThreadSno]);
                return;
            }
            int set = 1;
                        
            setsockopt(self.fdCustomTimerModifyWaitTimeReadPipe, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
            int write = 1;
            setsockopt(self.fdCustomTimerModifyWaitTimeWritePipe, SOL_SOCKET, SO_NOSIGPIPE, (void *)&write, sizeof(int));
            
            //socket一般都处于可写状态,除了网卡满了写不进去的罕见情况,并且若时线程外发送的消息都写了管道消息,管道有数据可度也会结束侦听,所以该处侦听一般都是立刻响应
            long ret = select(self.fdCustomTimerModifyWaitTimeReadPipe + 1, &read_fd_set, NULL, NULL, &tv);//核心

问题就出在tv.tv_sec是个long类型,给他传一个NSUIntegerMax(负数)就报22参数错误了。

目录
相关文章
|
6月前
|
存储 关系型数据库 MySQL
MySQL数据库——存储过程-条件处理程序(通过SQLSTATE指定具体的状态码,通过SQLSTATE的代码简写方式 NOT FOUND)
MySQL数据库——存储过程-条件处理程序(通过SQLSTATE指定具体的状态码,通过SQLSTATE的代码简写方式 NOT FOUND)
43 0
MySQL数据库——存储过程-条件处理程序(通过SQLSTATE指定具体的状态码,通过SQLSTATE的代码简写方式 NOT FOUND)
|
7月前
|
API Android开发 开发者
debug常见错误,出现debug时出现跑进为条件为false的if语句,DELETE_FAILED_INTERNAL_ERROR Error while In
debug常见错误,出现debug时出现跑进为条件为false的if语句,DELETE_FAILED_INTERNAL_ERROR Error while In
42 5
|
网络协议
排错-tcpreplay回放错误:send() [218] Message too long (errno = 90)
排错-tcpreplay回放错误:send() [218] Message too long (errno = 90)
260 0
|
C语言 C++
C语言程序入门——新手错误大全,常见的错误,总有一个适合你(一)易错点:main报错,error: ld returned 1 exit status报错,scanf与printf报错······
很多人在运行程序时,看到提示“error: ld returned 1 exit status”不知所措,自己代码没有任何问题,就是运行不起来,这是因为,自己上一个程序仍在运行,还未关闭,只要将上一个程序关掉,一切就迎刃而解了。常见的,如很多人喜欢装的杀毒软件,360,安全管家什么的,当你运行时,程序可能会被检测为高危程序,惨被清除,导致程序什么也没显示。正常情况下,无需杀毒软件,只要正常使用互联网,保证自己纯净上网后,杀毒软件就像累赘,可有可无。解决方法:输入时的格式必须与scanf里的格式一模一样。..
C语言程序入门——新手错误大全,常见的错误,总有一个适合你(一)易错点:main报错,error: ld returned 1 exit status报错,scanf与printf报错······
|
关系型数据库 MySQL 数据库
MySQL“错误1005(HY000):无法创建表'foo#sql-12c_4'(errno:150)”
MySQL“错误1005(HY000):无法创建表'foo#sql-12c_4'(errno:150)”
199 0
|
关系型数据库 MySQL 数据库
错误代码:1005无法创建表“…”(错误号:150)
错误代码:1005无法创建表“…”(错误号:150)
177 0
|
关系型数据库 MySQL 数据库
mysql 常见错误:Can't create table... errno150原因分析
mysql 常见错误:Can't create table... errno150原因分析
324 0
BrokenPipeError: [Errno 32] Broken pipe解决方法
BrokenPipeError: [Errno 32] Broken pipe解决方法
1450 0