基于Linux平台的高级IO扩展函数
由于read、readv、write和writev函数一次读或写有时并不能满足所要求的数据,因此需要多次调用直到要求的字节数或者出错。针对这4个系统调用,编写了对应的xxxn版本,实现如下
从以上代码可看出,readvn和writevn的实现并不是循环对每一个缓冲区简单地调用readn或writen,而是多次调用原生的readv或writev,因为对于读写多个缓冲区,使用readv或writev的效率通常要比多次调用read或write高,所以这样做就会尽可能减少系统调用的次数,提高效率。
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
}
/**********************************************************************************************************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
else42
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
}



浙公网安备 33010602011771号