linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Advice on mmap() "feature"
@ 2012-09-16 19:21 Mark Jackson
  2012-09-16 20:52 ` richard -rw- weinberger
  2012-09-17 11:17 ` Alan Cox
  0 siblings, 2 replies; 4+ messages in thread
From: Mark Jackson @ 2012-09-16 19:21 UTC (permalink / raw)
  To: lkml

Apologies if this is the wrong place to post this query.  Please feel 
free to redirect me to the correct place.

I have come across a weird (but documented [1]) "feature" of mmap(), 
which is:-

"The mmap()function adds an extra reference to the file associated with 
the file descriptor fildeswhich is not removed by a subsequent close() 
on that file descriptor. This reference is removed when there are no 
more mappings to the file."

In my embedded application, this is resulting in the consumption of 
available file descriptors.

As an example I wrote the following test running on Ubuntu 11.04 64bit.

#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <sys/mman.h>

#define FRAM_SIZE            (64 * 1024)
#define FRAM_BASE_ADDRESS    0x00000000

int main(int argc, char **argv)
{
     int i;
     for (i = 0; i < 5000; i++)
     {
         // open the fram device
         int m_fdFram = open("/dev/mem", O_RDWR | O_SYNC);
         if (m_fdFram < 0)
         {
             printf("could not open /dev/mem, exiting with errno %d\n", 
errno);
             return 0;
         }

         // map the device to memory
         char *m_pFram = (char *)mmap(    0,
                                         FRAM_SIZE * sizeof(unsigned short),
                                         PROT_READ | PROT_WRITE,
                                         MAP_SHARED,
                                         m_fdFram,
                                         FRAM_BASE_ADDRESS);
         if ((int)m_pFram == -1)
         {
             close(m_fdFram);
             m_fdFram = -1;
             printf("could not mmap, exiting with errno %d\n", errno);
             return 0;
         }

         // now remove the mapping
         if (m_pFram)
         munmap(m_pFram, FRAM_SIZE);

         if (m_fdFram != -1)
             close(m_fdFram);
     }

     puts("sleeping");
     sleep(50);

     return 0;
}

$ gcc test.c -o test
$ cat /proc/sys/fs/file-nr
10016    0    387704
$ ./test &
sleeping
$ cat /proc/sys/fs/file-nr
15008    0    387704

As can be seen, when I run the test, it consumes 5000 fd's, but only 
releases them when the application closes, 50 seconds later.

My application is designed to run for many years without a restart, 
spawning other tasks to do various system jobs, these fd's never seem to 
get released, and eventually the system runs out of available fd's.

So my questions are:-

(a) Since all the mappings have been removed, so why don't the fd's get 
released ?

(b) Can I somehow force some form of garbage collection to allow the 
fd's to be freed up ?

Again, apologies if this is the wrong place to ask, but I'm out of ideas.

Thanks in advance
Mark JACKSON

[1] http://pubs.opengroup.org/onlinepubs/007908775/xsh/mmap.html

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Advice on mmap() "feature"
  2012-09-16 19:21 Advice on mmap() "feature" Mark Jackson
@ 2012-09-16 20:52 ` richard -rw- weinberger
  2012-09-17  7:54   ` Mark Jackson
  2012-09-17 11:17 ` Alan Cox
  1 sibling, 1 reply; 4+ messages in thread
From: richard -rw- weinberger @ 2012-09-16 20:52 UTC (permalink / raw)
  To: Mark Jackson; +Cc: lkml

On Sun, Sep 16, 2012 at 9:21 PM, Mark Jackson <mpfj-list@mimc.co.uk> wrote:
> Apologies if this is the wrong place to post this query.  Please feel free
> to redirect me to the correct place.
>
> I have come across a weird (but documented [1]) "feature" of mmap(), which
> is:-
>
> "The mmap()function adds an extra reference to the file associated with the
> file descriptor fildeswhich is not removed by a subsequent close() on that
> file descriptor. This reference is removed when there are no more mappings
> to the file."
>
> In my embedded application, this is resulting in the consumption of
> available file descriptors.
>
> As an example I wrote the following test running on Ubuntu 11.04 64bit.
>
> #include <fcntl.h>
> #include <errno.h>
> #include <stdio.h>
> #include <sys/mman.h>
>
> #define FRAM_SIZE            (64 * 1024)
> #define FRAM_BASE_ADDRESS    0x00000000
>
> int main(int argc, char **argv)
> {
>     int i;
>     for (i = 0; i < 5000; i++)
>     {
>         // open the fram device
>         int m_fdFram = open("/dev/mem", O_RDWR | O_SYNC);
>         if (m_fdFram < 0)
>         {
>             printf("could not open /dev/mem, exiting with errno %d\n",
> errno);
>             return 0;
>         }
>
>         // map the device to memory
>         char *m_pFram = (char *)mmap(    0,
>                                         FRAM_SIZE * sizeof(unsigned short),
>                                         PROT_READ | PROT_WRITE,
>                                         MAP_SHARED,
>                                         m_fdFram,
>                                         FRAM_BASE_ADDRESS);
>         if ((int)m_pFram == -1)
>         {
>             close(m_fdFram);
>             m_fdFram = -1;
>             printf("could not mmap, exiting with errno %d\n", errno);
>             return 0;
>         }
>
>         // now remove the mapping
>         if (m_pFram)
>         munmap(m_pFram, FRAM_SIZE);

You unmap less memory than you map...

-- 
Thanks,
//richard

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Advice on mmap() "feature"
  2012-09-16 20:52 ` richard -rw- weinberger
@ 2012-09-17  7:54   ` Mark Jackson
  0 siblings, 0 replies; 4+ messages in thread
From: Mark Jackson @ 2012-09-17  7:54 UTC (permalink / raw)
  To: richard -rw- weinberger; +Cc: lkml

On 16/09/12 21:52, richard -rw- weinberger wrote:
> On Sun, Sep 16, 2012 at 9:21 PM, Mark Jackson <mpfj-list@mimc.co.uk> wrote:
>>         // now remove the mapping
>>         if (m_pFram)
>>         munmap(m_pFram, FRAM_SIZE);
> 
> You unmap less memory than you map...
> 

I hang my head in shame ... what a stupid mistake to miss !!

Thank you


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Advice on mmap() "feature"
  2012-09-16 19:21 Advice on mmap() "feature" Mark Jackson
  2012-09-16 20:52 ` richard -rw- weinberger
@ 2012-09-17 11:17 ` Alan Cox
  1 sibling, 0 replies; 4+ messages in thread
From: Alan Cox @ 2012-09-17 11:17 UTC (permalink / raw)
  To: Mark Jackson; +Cc: lkml

> (a) Since all the mappings have been removed, so why don't the fd's get 
> released ?

Because your code is buggy.

Firstly its files it keeps a reference to not file handles, so your close
closes the file handle. You do however end up with lots of file structs
pinned and that's because you've got a bug.

You map twice as much as you unmap, the kernel therefore keeps the second
half mapped for you. Fix your munmap and all will be happy.

You owe the oracle an ice cream

Alan

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2012-09-17 11:12 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-09-16 19:21 Advice on mmap() "feature" Mark Jackson
2012-09-16 20:52 ` richard -rw- weinberger
2012-09-17  7:54   ` Mark Jackson
2012-09-17 11:17 ` Alan Cox

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).