2013-03-21 113 views
3

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

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

有人可以帮忙吗?

注意:我正在观察“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); 
     } 
    } 
} 
+1

什么是内存使用情况:常驻还是虚拟?你也尝试过用[valgrind](http://valgrind.org/docs/manual/quick-start.html)来运行你的程序吗?作为一个附注,你可能想用'memset'替换非标准的'bzero'函数。 – 2013-03-21 01:55:34

+0

@CristianCuupitu谢谢你的回复。我应该澄清一下,在运行过程中,流程本身的内存使用情况似乎没有多大变化(无论是驻留还是虚拟)。但是我看到整个系统内存使用量增加(按照顶部列出的总内存使用量)。当我删除文件时,系统内存再次下降。也许它与我的代码无关?它可能是一个系统问题?写入磁盘的文件是否会占用系统内存? – justin1080602 2013-03-21 02:23:16

+3

Linux使用内存来缓存IO操作,可能是因为您看到缓存内存使用情况。 – Necrolyte2 2013-03-21 02:47:23

回答

0

这是因为写入的缓存机制。如果您有很多客户端尝试写入文件,则IO缓冲区会填充内核内存,但实际上并不会写入该文件,除非您关闭套接字或填充缓冲区。你可以通过刷新缓冲区来解决这个问题。其他人提出的建议是摆脱stdio中的写入和读取包装,并使用内核调用写入,因为这将有助于性能,并且可能会自动刷新缓冲区。

你可以使用fsync()顺便刷新。