如何使read和write操作不受平台干扰

54 篇文章 1 订阅
    在 使fread和fwrite的运用更加的强壮文中,讲解了如何使用fread和fwrite。我们会发现,其实在Unix/Linux系统中,用fread和fwrite并不是一个最佳选择,因为C标准库屏蔽了一些错误信息,我们仅仅能够使用ferror函数来判断是否出现了错误,但是是何种错误,我们无法知晓。对于一个使用中断的系统而言,我们都希望对于系统调用是可从入的,所有有些网友喜欢在struct sigaction的sa_flags中将SA_RESTART标记加入,虽然我们达到了所希望的,但是同时我们的代价就是无法实现某些功能,比如说使用时钟中断来实现I/O读写超时功能。当然我们依然可以使用select或者poll函数来实现这种功能,不过是否现存所有unix/linux都支持它们并且其他平台呢?对于信号捕捉函数而言,一般都不指定SA_RESTART标记,因为这些可能会对程序的移植性带来一些问题(比如说将部分依赖于SA_RESTART的程序移植到一个不关心SA_RESTART的程序中去,导致我们可能不得不改动所有相关的中断处理函数,并且这种改动也可能是无法进行的)。
    那么如何来解决这些问题呢?我觉得我们可能要在read/write上封装一层,比如提供readn/writen。它的主要功能是减少平台之间的关联作用,比如在Unix/Linux系统中,有中断干扰。但是在windows系统中没有这个方面的干扰。对于上层而言,它只要知道readn/writen成功的时候返回>=0的值,否则返回-1。对于具体是用read/write还是用fread/fwrite实现并不关心。比如说,我们在unix/linux平台我们可能会偏重于read/write来实现,在windows平台我们可能偏重于fread/fwrite来实现。
    为了给网友一个演示,我在unix/linux平台写了一段程序,它仅仅是作为参考。希望对网友有所帮助!
#include <iostream>
#include <memory.h>

#include <assert.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

using namespace std;

#define __rwFn( fd, opFn, buf, count )  ({                              /
        ssize_t __realCount;                                                   /
        for ( ; ; )                                                            /
        {                                                                      /
                __realCount = opFn( fd, buf, count );                   /
                if ( __realCount == -1 && errno == EINTR )              /
                        continue;                                              /
                break;                                                         /
        }                                                                      /
        __realCount;                                                           /
        })

#ifndef __rwFn

ssize_t readn( int fd, void *buf, size_t count )
{
        for ( ; ; )
        {
                ssize_t loaded = read( fd, buf, count );
                if ( loaded == -1 && errno == EINTR )
                                continue;

                return loaded;
        }
}

ssize_t writen( int fd, const void *buf, size_t count )
{
        for ( ; ; )
        {
                ssize_t saved = write( fd, buf, count );
                if ( saved == -1 && errno == EINTR )
                        continue;

                return saved;
        }
}

#else

#define readn( fd, buf, count )         __rwFn( fd, read, buf,  count )
#define writen( fd, buf, count )        __rwFn( fd, write, buf, count )

#endif

class AutoFile
{
        int fd;

        AutoFile( const AutoFile &rhs );
        AutoFile& operator=( const AutoFile &rhs );
public:
        AutoFile( const char *file, int flags )
                : fd ( -1 )
        {
                assert( file != NULL );
                fd = open( file, flags );
                assert( fd != -1 );
        }

        operator int ()
        {
                return fd;
        }

        ~AutoFile()
        {
                if ( fd != -1 );
                        close( fd );
        }
};

int main( void )
{
        AutoFile fd( "./test.cpp", O_RDONLY );

        struct stat st_buf;

        int rs = fstat( fd, &st_buf );
        assert( rs != -1 );
        assert( st_buf.st_blksize > 0 );
        cout << "Good I/O block size = " << st_buf.st_blksize << endl;

        ssize_t count = (ssize_t) st_buf.st_blksize;
        char *buf =  new char[ count ];
        assert( buf != NULL );

        for ( ssize_t loaded; (loaded = readn( fd, buf, count )) > 0  ; )
        {
                ssize_t saved = writen( STDOUT_FILENO, buf, loaded );
                assert( saved == loaded );
        }

        delete[] buf;

        return 0;
}

  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值