内核循环缓冲实现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

Your Answer