3

我有一个用 C 编写的简单服务器程序,该程序在 Ubuntu Linux 发行版上运行。该程序旨在侦听从客户端发送的消息,将这些消息写入文件(每条消息进入一个单独的文件),并在收到并存储消息后向客户端发送确认。

我注意到,随着服务器继续接收和存储消息,可用系统内存量迅速减少并继续减少,直到消息停止。当没有消息被发送时,内存保持不变。但是,我也注意到我可以通过从磁盘中删除写入的文件来再次释放内存(即使服务器仍在运行,我也可以这样做)。因此,我相信内存问题与我的文件操作有关,尽管我看不到写入文件的代码有任何问题。

有人可以帮忙吗?

注意:我用“top”观察内存使用情况。

我已经包含了该程序的摘录。下面的函数处理来自客户端的输入并将该信息写入文件。这是我目前认为问题所在:

void handleinput (int sock)
{
    char filename[strlen(tempfolder) + 27];
    generatefilename(filename);

    int rv;
    int n = 1;
    int received = 0;
    char buffer[BUFFER_SIZE];
    FILE *p = NULL;
    fd_set set;
    char response[768];
    struct timeval timeout;
    timeout.tv_sec = 360;
    timeout.tv_usec = 0;

    FD_ZERO(&set);
    FD_SET(sock, &set);

    bzero(buffer, BUFFER_SIZE);
    bzero(response, sizeof response);
    rv = select(sock + 1, &set, NULL, NULL, &timeout);
    if (rv == -1)
    {
        error("error on select in handleinput");
        close(sock);
        exit(1);
    }
    else if (rv == 0)
    {
        close(sock);
        exit(0);
    }
    else
    {
            n = read(sock, buffer, BUFFER_SIZE-1);
            if (n <= 0)
            {
                close(sock);
                exit(0);
            }
    }

    // open file
    if (n != 0)
    {
        p = fopen(filename, "a");
        if (p == NULL)
        {
            error("ERROR writing message to file");
            close(sock);
            exit(1);
        }
    }

    // loop until full message is received
    while (n != 0)
    {
        if (n < 0)
        {
            error("ERROR reading from socket");
            close(sock);
            exit(1);
        }

        received = 1;
        // write content to file
        fwrite(buffer, strlen(buffer), 1, p);

        if (buffer[strlen(buffer)-1] == 0x1c)
        {
            break;
        }

        bzero(buffer, BUFFER_SIZE);
        rv = select(sock + 1, &set, NULL, NULL, &timeout);
        if (rv == -1)
        {
            error("ERROR select in loop in handleinput");
            close(sock);
            exit(1);
        }
        else if (rv == 0)
        {
            close(sock);
            exit(0);
        }
        else
        {
            n = read(sock, buffer, BUFFER_SIZE-1);
        }
    }

    // close file if we opened it earlier
    if (p != NULL)
    {
        fclose(p);
    }

    // send acknowledgement back to client
    if (received == 1)
    {
        generateResponse(response, filename);
        n = write(sock, response, strlen(response));

        if (n < 0)
        {
            error("ERROR writing to socket");
            close(sock);
            exit(1);
        }
    }
}
4

1 回答 1

0

这是因为写入的缓存机制。如果您有很多客户端尝试写入文件,则 IO 缓冲区会填充内核内存,但在您关闭套接字或缓冲区填满之前不会真正写入该文件。您可以通过刷新缓冲区来解决此问题。其他一些人的建议是摆脱 stdio 中的写入和读取包装器,而只使用内核调用 write,因为这将有助于提高性能并且可能会自动刷新缓冲区。

顺便说一句,您可以使用 fsync() 刷新。

于 2013-05-10T14:41:33.497 回答