Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1740759
  • 博文数量: 438
  • 博客积分: 9799
  • 博客等级: 中将
  • 技术积分: 6092
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-25 17:25
文章分类

全部博文(438)

文章存档

2019年(1)

2013年(8)

2012年(429)

分类: 系统运维

2012-04-01 20:31:23

管道、FIFO和一些设备,尤其是终端、网络和STREAMS设备,有以下两个属性。


1、一个read操作可能返回比请求更少,即使我们没有遇到文件尾。这不是一个错误,我们应该简单地继续从设备读。


2、一个write操作也可能返回比我们指定的少。例如它可能因为向下的流模块的控制流限制。再次,这不是一个错误,我们应该继续写剩余的数据。(通常,这从一个write而来的短返回只在非阻塞描述符或如果一个信号被捕获是发生。)


我们将不会在读写磁盘文件时看到这个发生,除了发文件系统没有空间,或我们达到了配额限制而我们不能全部写完我们请求的。


一般说来,当我们读或写一个管道、网络设备或终端时,我们需要考虑这些特性。我们可以使用以下两个函数来读写N字节的数据,让这些函数处理一个可能的比请求小的值。这两个函数简单地调用read或write,尽可能多次地来读写整个N字节的数据。



  1. #include "apue.h" /* 自己写的函数 */

  2. ssize_t readn(int filedes, void *buf, size_t nbytes);
  3. ssize_t writen(int filedes, void *buf, size_t nbytes);

  4. 两者返回读或写的字节数,错误返回-1。


我们定义这些函数,作为以后例子的便利工具,和本文许多例子里使用的错误处理例程一样。readn和writen函数不是任何标准的一部分。


我们调用writen,每当我们向某个我们提到的文件类型写时,但是我们只在我们提前知道我们将收到特定字节数量时才调用readn。下面的代码展示了readn和writen的实现,我们将在后面的例子里使用它们。



  1. #include <fcntl.h>

  2. ssize_t /* Read "n" bytes from a descriptor */
  3. readn(int fd, void *ptr, size_t n)
  4. {
  5.     size_t nleft;
  6.     ssize_t nread;

  7.     nleft = n;
  8.     while (nleft > 0) {
  9.         if ((nread = read(fd, ptr, nleft)) < 0) {
  10.             if (nleft == n)
  11.                 return(-1); /* error, return -1 */
  12.             else
  13.                 break; /* error, return amount read so far */
  14.         } else if (nread == 0) {
  15.             break; /* EOF */
  16.         }
  17.         nleft -= nread;
  18.         ptr += nread;
  19.     }
  20.     return(n - nleft); /* return >= 0 */
  21. }

  22. ssize_t /* Write "n" bytes to a descriptor */
  23. writen(int fd, const void *ptr, size_t n)
  24. {
  25.     size_t nleft;
  26.     ssize_t nwritten;

  27.     nleft = n;
  28.     while (nleft > 0) {
  29.         if ((nwritten = write(fd, ptr, nleft)) < 0) {
  30.             if (nleft == n)
  31.                 return(-1); /* error, return -1 */
  32.             else
  33.                 break; /* error, return amout written so far */
  34.         } else if (nwritten == 0) {
  35.             break;
  36.         }
  37.         nleft -= nwritten;
  38.         ptr += nwritten;
  39.     }
  40.     return(n - nleft); /* return >= 0 */
  41. }


注意如果我们碰到一个错误而之前读过或写过任何数据,那么我们返回已经传输的数据而不是错误。相似地,如果我们在读时到达文件尾,我们返回拷贝到调用者缓冲的字节数,如果我们已经成功读了一些数据,但并没有满足请求的量。
阅读(1203) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~