内核循环缓冲实现seek功能相关的问题
对于网络数据的发送,一次操作返回值可能小于所指定输出的字节数。对于从客户端发送一个文件到服务器端的例子,可以从两个方面进行一些处理:
1、多次发送没有发送了的数据
ssize_t sendn(int sock_fd, const void *ptr, size_t n)
{
size_t nleft = n;
ssize_t nwritten;
while(nleft > 0) {
if((nwritten = send(sock_fd, ptr, nleft, 0)) < 0) {
if(nleft == n)
return -1;
else
break;
} else if(nwritten == 0)
break;
nleft -= nwritten;
ptr += nwritten;
}
return (n - nleft);
}
2、使用lseek指定到文件正确的读写位置
while(1) {
bzero(buffer, BUFFER_SIZE);
size = read(file_fd, buffer, BUFFER_SIZE);
if(size <= 0)
break;
if((nsendsize = sendn(sock_fd, buffer, size)) < 0) {
perror("sendn error!\n");
lseek(file_fd, -size, SEEK_CUR);
return -1;
}
if(nsendsize < size)
lseek(file_fd, nsendsize - size, SEEK_CUR);
}
如果读取不是文件,而是一个循环缓冲区(例如内核中的kfifo,请参考源码了解),那么第1步的处理对于它来说同样有效,第2步的处理则无效。那么就需要实现一个类似lseek的功能,感觉挺复杂的,需要考虑的东西比较多。目前主要考虑到以下一些问题:
a、(in - out)的差值会大于size(以上问题的情况,offset小于0);
b、in和out两者都溢出或则只有in溢出后的偏移处理(关于溢出的情况,可以参考这个
问题
);
c、(out = out + offset)的各种可能情况;
各位,对该问题有什么建议或者想法?
linux-kernel Ubuntu c 内核 Linux
joehee
10 years, 7 months ago