Chinaunix首页 | 论坛 | 博客
  • 博客访问: 40318
  • 博文数量: 17
  • 博客积分: 750
  • 博客等级: 军士长
  • 技术积分: 160
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-19 17:39
文章分类
文章存档

2009年(17)

我的朋友

分类: C/C++

2009-11-04 20:07:54

下面是read和write的函数原型
#include
ssize_t read(int fd, void *buf, size_t count);    //count通常取sizeof(buf)
返回值:若成功,返回读取的字节数(不一定是count),出错返回-1并设置errno,如果在调read之前已到达文件末尾,则这次read返回0。文件的当前读写位置向后移。

#include
ssize_t write(int fd, const void *buf, size_t count);
返回值:若成功,返回写入的字节数(不一定是count),出错返回-1并设置errno。

当read普通的文件如磁盘文件时,返回值通常=count,若if(n=read( fd, buf,  count)>0)
write( fd, buf, n);
但是读管道、FIFO、终端和socket时,很可能
当write普通的文件如磁盘文件时,返回值通常=count,若if(write( fd, buf,  count)!=count)
err_sys("write error");
但是write管道、FIFO、终端和socket时,很可能
于是对管道、FIFO、终端和socket等文件,我们自定义了下面的函数,直至读写了指定的n字节数据才返回。
版本1

#include "apue.h"
ssize_t readn(int fd, void *ptr, size_t n)
{
    size_t        nleft;
    ssize_t        nread;

    nleft = n;
    while (nleft > 0) {
        if ((nread = read(fd, ptr, nleft)) < 0) {        //当read返回-1,

            if (nleft == n)
                return(-1);                                /*若第一次read时出错, readn 返回 -1 */
            else
                break;                             /*若读了一些数据后出错, readn返回已经读的字节数,而不出错返回 */
        } else if (nread == 0) {                        //当read返回0时,不再读下去,readn返回已经读的字节数

            break; /* EOF */
        }
        nleft -= nread;                                    //当read返回值>0但不等于n时,继续读

        ptr += nread;
    }
    return(n - nleft); /* return >= 0 */
}

ssize_t writen(int fd, const void *ptr, size_t n)
    size_t        nleft;
    ssize_t        nwritten;

    nleft = n;
    while (nleft 0) {
        if ((nwritten = write(fd, ptr, nleft)) < 0) {    //当write返回-1,

            if (nleft == n)                                /*若第一次write时出错, writen 返回 -1 */
                return(-1);
            else
                break;                             /*若写了一些数据后出错, writen返回已经读的字节数,而不出错返回 */
        } else if (nwritten == 0) {                        //当write返回0时,不再写下去,writen返回已经读的字节数

            break;
        }
        nleft -= nwritten;                                //当write返回值>0但不等于n时,继续写

        ptr += nwritten;
    }
    return(n - nleft); /* return >= 0 */
}


上述版本在read write出错后,若已经读写了一些数据,则返回读写的字节量,而非出错返回。但在read write出错后没有检查errno判断是否因为被信号中断而出错。

版本2

#include    "unp.h"
ssize_t                        
readn(int fd, void *vptr, size_t n)
{
    size_t    nleft;
    ssize_t    nread;
    char    *ptr;

    ptr = vptr;
    nleft = n;
    while (nleft > 0) {
        if ( (nread = read(fd, ptr, nleft)) < 0) {    //当read返回-1,

            if (errno == EINTR)
                nread = 0;                            /*若出错是因为被信号中断,继续读*/
            else
                return(-1);                            //若不是因为被信号中断而出错,则不再读readn返回-1
        } else if (nread == 0)                        //当read返回0时,不再读下去,readn返回已经读的字节数
            break;                /* EOF */


        nleft -= nread;                                //当read返回值>0但不等于n时,继续读

        ptr += nread;
    }
    return(n - nleft);        /* return >= 0 */
}

ssize_t                        
writen(int fd, const void *vptr, size_t n)
{
    size_t        nleft;
    ssize_t        nwritten;
    const char    *ptr;

    ptr = vptr;
    nleft = n;
    while (nleft > 0) {                                        
        if ( (nwritten = write(fd, ptr, nleft)) <= 0) {        //当write出错返回-1或者返回0时,

            if (nwritten < 0 && errno == EINTR)
                nwritten = 0;                                /*若出错返回-1是因为被信号中断,继续写 */
            else
                return(-1);                                    //若不是因为被信号中断而出错返回-1或者 返回0时,则不再写writen返回-1

        }

        nleft -= nwritten;                                    //当write返回值>0但不等于n时,继续写

        ptr += nwritten;
    }
    return(n);
}

上述版本在read write出错后,不返回读写的字节量,而是出错返回-1。但在read write出错后检查errno判断是否因为被信号中断而出错,若是因为被信号中断,继续读写。

    在将数据写到像socket这样的文件类型时,就可以调用writen,但通常只调用read来接收来自这些设备的数据,只有当事先就知道接收数据的数据量时,才调用readn。

again:
    while ( (n = read(sockfd, buf, MAXLINE)) > 0)    //调用read

        writen(sockfd, buf, n);                        //调用writen


    if (n < 0 && errno == EINTR)
        goto again;
    else if (n < 0)
        err_sys("str_echo: read error");
}


阅读(1201) | 评论(0) | 转发(0) |
0

上一篇:非阻塞IO

下一篇:linux中的定时

给主人留下些什么吧!~~