由于read、readv、write和writev函數(shù)一次讀或?qū)懹袝r并不能滿足所要求的數(shù)據(jù),因此需要多次調(diào)用直到要求的字節(jié)數(shù)或者出錯。針對這4個系統(tǒng)調(diào)用,編寫了對應的xxxn版本,實現(xiàn)如下
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的實現(xiàn)并不是循環(huán)對每一個緩沖區(qū)簡單地調(diào)用readn或writen,而是多次調(diào)用原生的readv或writev,因為對于讀寫多個緩沖區(qū),使用readv或writev的效率通常要比多次調(diào)用read或write高,所以這樣做就會盡可能減少系統(tǒng)調(diào)用的次數(shù),提高效率。
posted on 2013-08-02 19:44
春秋十二月 閱讀(1770)
評論(0) 編輯 收藏 引用 所屬分類:
System