由于read、readv、write和writev函数一次读或写有时并不能满足所要求的数据,因此需要多次调用直到要求的字节数或者出错。针对这4个系统调用,编写了对应的xxxn版本,实现如下
1
/**********************************************************************************************************
2
In the following four functions,the optional parameter tran indicate the number of bytes read or written,or -1 if an error occurred.
3
On success,return true indicate all data had been read or written successfully,otherwise in other cases,return false indicate error or partial success.
4
**********************************************************************************************************/
5
6
bool readn(int fd,void* buf,size_t cnt,ssize_t* tran/**//*=NULL*/)
7

{
8
size_t left = cnt;
9
ssize_t ret;
10
char* ptr = (char*)buf;
11
12
while(left > 0)
{
13
ret = read(fd,ptr,left);
14
if(ret > 0)
{
15
left -= ret;
16
ptr += ret;
17
}else if(0==ret || left != cnt)
18
break;
19
else
{
20
if(tran) *tran = -1;
21
return false;
22
}
23
}
24
if(tran) *tran = cnt-left;
25
return 0==left;
26
}
27
28
bool writen(int fd,const void* buf,size_t cnt,ssize_t* tran/**//*=NULL*/)
29

{
30
size_t left = cnt;
31
ssize_t ret;
32
char* ptr = (char*)buf;
33
34
while(left > 0)
{
35
ret = write(fd,ptr,left);
36
if(ret > 0)
{
37
left -= ret;
38
ptr += ret;
39
}else if(0==ret || left != cnt)
40
break;
41
else
42
if(tran) *tran = -1;
43
return false;
44
}
45
if(tran) *tran = cnt-left;
46
return 0==left;
47
}
48
49
static int get_iov_tran_index(const struct iovec* iov,int iovcnt,size_t trans,size_t& tran)
50

{
51
size_t cnt = 0; int i;
52
53
for(i=0;i < iovcnt;++i)
{
54
cnt += iov[i].iov_len;
55
if(trans < cnt)
{
56
tran = iov[i].iov_len - (cnt - tran);
57
break;
58
}
59
}
60
return i;
61
}
62
63
bool readvn(int fd,const struct iovec* iov,int iovcnt,ssize_t* tran/**//*=NULL*/)
64

{
65
if(iovcnt > IOV_MAX)
{
66
if(tran) *tran = -1;
67
errno = EINVAL;
68
return false;
69
}
70
size_t all_cnt = 0,all_tran = 0,one_tran;
71
ssize_t ret;
72
73
struct iovec _iov[IOV_MAX];
74
int i;
75
for(i=0;i < iovcnt;++i)
{
76
_iov[i] = iov[i];
77
all_cnt += iov[i].iov_len;
78
}
79
80
i = 0;
81
do
{
82
ret = readv(fd,&_iov[i],iovcnt-i);
83
if(ret > 0)
{
84
all_tran += ret;
85
if(all_tran==all_cnt)
86
break;
87
88
i = get_iov_tran_index(iov,iovcnt,all_tran,one_tran);
89
assert(i < iovcnt);
90
_iov[i].iov_base = iov[i].iov_base + one_tran;
91
_iov[i].iov_len = iov[i].iov_len - one_tran;
92
93
}else if(0==ret)
94
break;
95
else
{
96
if(tran) *tran = -1;
97
return false;
98
}
99
}while(all_tran < all_cnt);
100
101
if(tran) *tran = all_tran;
102
return all_tran==all_cnt;
103
}
104
105
bool writevn(int fd,const struct iovec* iov,int iovcnt,ssize_t* tran/**//*=NULL*/)
106

{
107
if(iovcnt > IOV_MAX)
{
108
if(tran) *tran = -1;
109
errno = EINVAL;
110
return false;
111
}
112
size_t all_cnt = 0,all_tran = 0,one_tran;
113
ssize_t ret;
114
115
struct iovec _iov[IOV_MAX];
116
int i;
117
for(i=0;i < iovcnt;++i)
{
118
_iov[i] = iov[i];
119
all_cnt += iov[i].iov_len;
120
}
121
122
i = 0;
123
do
{
124
ret = writev(fd,&_iov[i],iovcnt-i);
125
if(ret > 0)
{
126
all_tran += ret;
127
if(all_tran==all_cnt)
128
break;
129
130
i = get_iov_tran_index(iov,iovcnt,all_tran,one_tran);
131
assert(i < iovcnt);
132
_iov[i].iov_base = iov[i].iov_base + one_tran;
133
_iov[i].iov_len = iov[i].iov_len - one_tran;
134
135
}else if(0==ret)
136
break;
137
else
{
138
if(tran) *tran = -1;
139
return false;
140
}
141
}while(all_tran < all_cnt);
142
143
if(tran) *tran = all_tran;
144
return all_tran==all_cnt;
145
} 从以上代码可看出,readvn和writevn的实现并不是循环对每一个缓冲区简单地调用readn或writen,而是多次调用原生的readv或writev,因为对于读写多个缓冲区,使用readv或writev的效率通常要比多次调用read或write高,所以这样做就会尽可能减少系统调用的次数,提高效率。
posted on 2013-08-02 19:44
春秋十二月 阅读(1765)
评论(0) 编辑 收藏 引用 所属分类:
System