首页 > 编程知识 正文

read函数功能,输入流read方法的返回值

时间:2023-05-04 22:19:17 阅读:27098 作者:453

考虑一下read函数的返回值。 《Unix高级环境编程》本书介绍了read的返回值。

实际读取的字节数可能会少于需要读取的字节数。

1 )读取普通文件时,在读取请求字节数之前已到达文件末尾。 例如,如果在到达文件末尾之前还有30字节,并且要求读取100字节,则read返回30,然后调用read返回0 (在文件末尾)。

2 )从终端设备读取时,通常一次最多读一行。

3 )从网络读取时,通过网络内的缓存机制,返回值有可能小于所请求的读字而结束。

4 )从管道或FIFO读取时,如果管道包含的字节数少于所需的字节数,则read只返回实际可用的字节数。

5 )从磁带等面向记录的设备读取时,一次最多返回一个记录。

6 )任一信号发生中断,读取了部分数据时。

作为第六个示例,一个进程发起了读取终端的操作,但是使用该终端设备的用户远离系统很长时间。 在这种情况下,进程可能被阻止了几个小时到几天,除非系统停机。

对于中断的读写系统调用,POSIX.1的语义在标准版本2001中进行了更改,在以前的版本中允许您选择如何处理部分读写数据量。 如果接收到read系统调用并将其传输到APP应用程序缓冲区,但未接收到APP应用程序请求的所有数据,则返回http://ww.Sina。

同样,如果write传输并中断了APP应用程序缓冲区中的部分数据,则操作系统将认为系统调用(write写入)失败,可以将errno设置为EINTR。 另一种处理方法是确保系统调用成功返回。 返回值是已经写入的数据量的一部分。

此时被中断,操作系统可以认为该系统调用(read读取)失败,并将errno设置为EINTR;另一种处理方式是允许该系统调用返回成功,返回值是已经接收到的数据。(这是早期处理方式)

与中断的系统调用相关的问题是必须显式处理错误返回。 典型的代码序列(进行一次操作,假设他被中断,我们想重新启动它)。

again:if(n=read ) FD,buf,BUFFSIZE ) )0) if ) errno==eintr ) { goto again;/* justaninterruptedsystemcall *//* handleothererrors */}为了帮助APP应用程序避免处理中断的系统调用,4.2 BSD自动重新启动中断的系统调用历史上,从System V派生的实现将这种系统调用视为失败,而BSD派生的实现则视为部分返回成功,2001版POSIX.1标准采用BSD风格语义。waite和waitpid在捕获信号时总是中断。 由于这种自动重新启动的处理方法也存在问题,一些APP应用程序不希望这些函数中断并重新启动。 因此,在4.3 BSD中,该过程可以基于每个信号来禁用字功能。

自动重启的系统调用包括:ioctl、read、ready、write、writev、wait和waitpid。其中前面的五个函数只有对低速设备进行操作时,才会被信号中断

3358 www.Sina.com/http://www.Sina.com/http://www.Sina.com /

errno的部分错误代码如下。

# defineeperm1/*操作notpermitted * /

# defineenoent2/* nosuchfileordirectory * /

#define ESRCH 3 /* No such process */

# define eintr4/*交互式系统呼叫* /

#定义Eio

          5  /* I/O error */
#define  ENXIO         6  /* No such device or address */
#define  E2BIG         7  /* Arg list too long */
#define  ENOEXEC       8  /* Exec format error */
#define  EBADF         9  /* Bad file number */
#define  ECHILD       10  /* No child processes */
#define  EAGAIN       11  /* Try again */

 

遇到的奇怪问题,read返回值-1,但是errno 为 0,然后导致返回值为-1,最后关闭了连接会话。

do{ t_left = _tcp_net_time_left(t_end, _get_time_ms()); if (0 == t_left) { DEBUG_MSG("recv_time endrn"); break; } recved_num = read(fd, buf + len_recv, len - len_recv); //因为打印消耗时间,并且errno的值可能被其他进程修改了,所以关闭打印,使用变量赋值 //DEBUG_MSG("read %d,%d", recved_num, errno); l_error = errno; if (recved_num > 0) { len_recv += recved_num; } else if (0 == recved_num ) { //return -1; //原代码是这样的,存在巨大隐患 continue; } else if ((recved_num < 0) && (l_error == EINTR || l_error == EWOULDBLOCK || l_error == EAGAIN)) { continue; } else //除去上面的情况,其余情况均认为read失败 { DEBUG_MSG("_tcp_net_recv_timeout err,errno:%d", l_error); return -1; }}while (len_recv < len);

 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。