You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modules-dev@httpd.apache.org by Pranesh Vadhirajan <va...@teralogics.com> on 2011/11/16 21:03:40 UTC

Apache shared memory implementation

Hello Everyone,

     I am trying to understand how to implement sharing of objects in memory
between various processes in apache.  I have been using the routines defined
in <sys/mman.h> to implement the shared memory mapping functionality.
However, I am not seeing any actual sharing of the objects in my output.  

 

I have attached the code segment of my module containing the request
handler:

 

#include "httpd.h"

#include "http_core.h"

#include "http_config.h"

#include <stdlib.h>

#include <time.h>

#include <sys/time.h>

#include <sys/types.h>

#include "sessions.h"

#include <regex.h>

#include <stdio.h>

#include <sys/mman.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <unistd.h>

 

 

void set_shared_region(int *shared_int)

{

   int fd;

 

   /* Create shared memory object and set its size */

   fd = shm_open("/myregion", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);

   if(fd == -1)

      fprintf(stderr,"shm_open error");

 

   if(ftruncate(fd, sizeof(int)) == -1)

       fprintf(stderr,"ftruncate error");

 

    /* Map shared memory object */

   shared_int = mmap(NULL, sizeof(int),PROT_READ | PROT_WRITE, MAP_SHARED,
fd, 0);

   if(shared_int == MAP_FAILED)

      fprintf(stderr,"mmap error");

}

 

int start_mutex()

{

   if(initial_mutex_value == 0)

   {

      if(sem_init(&session_mutex,1,1) < 0)

      {

         fprintf(stderr,"error initializing semaphore");

         return 0;

      }

      initial_mutex_value = 1;

   }

   return 1;

}

 

static int counter_handler(request_rec* r) 

{

   char time_buffer[30]; 

   char entry[1024];

   long int tid,pid;

   apr_ctime(time_buffer,r->request_time);

   start_mutex();

   sem_wait(&session_mutex);

   set_shared_region(&ctr);

   ctr++;

   sem_post(&session_mutex);

   //tid = (long int)getthreadid();

   pid = (long int)getpid();

   sprintf(entry,"counter: %i, thread: %ld, process: %ld, request: %s,
time: %s;",ctr,(long int)0,pid,r->the_request,time_buffer);

   tempToDB(entry);

 

   return DECLINED;

}

 

static void counter_register_hooks (apr_pool_t *p)

{

   ap_hook_handler(counter_handler, NULL, NULL, APR_HOOK_REALLY_FIRST);

}

 

module AP_MODULE_DECLARE_DATA counter_module = 

{

  STANDARD20_MODULE_STUFF,

  NULL,//uvds_metrics_dir_conf,      /* Per-Directory Configuration */

  NULL,//uvds_metrics_dir_merge,           /* Directory Config Merger */

  NULL,//uvds_metrics_server_conf,         /* Per-Server Configuration */

  NULL,//uvds_metrics_server_merge,  /* Server Config Merger */

  NULL,//uvds_metrics_cmds,                /* Command Table (Directives) */

  counter_register_hooks             /* Registering Hooks */

};

 

The handler code uses the variable ctr which is defined in the header file
"sessions.h" .  Here's the relevant segment in sessions.h:

 

                                                #include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include "libpq-fe.h"

#include <semaphore.h>

 

sem_t session_mutex;

int initial_mutex_value = 0;

int ctr = 0;

 

void tempToDB(char *entry);

 

 

 

Here's the output of my code:  

 

                                                64201;"counter: 1, thread:
0, process: 18194, request: POST /login?destination=login HTTP/1.1,  time:
Wed Nov 16 19:56:04 2011;"

64202;"counter: 2, thread: 0, process: 18194, request: POST
/login?destination=login HTTP/1.1,  time: Wed Nov 16 19:56:04 2011;"

64203;"counter: 3, thread: 0, process: 18194, request: GET /login HTTP/1.1,
time: Wed Nov 16 19:56:05 2011;"

64204;"counter: 4, thread: 0, process: 18194, request: GET /login HTTP/1.1,
time: Wed Nov 16 19:56:05 2011;"

64205;"counter: 5, thread: 0, process: 18194, request: GET /dashboard
HTTP/1.1,  time: Wed Nov 16 19:56:06 2011;"

64206;"counter: 6, thread: 0, process: 18194, request: GET /dashboard
HTTP/1.1,  time: Wed Nov 16 19:56:06 2011;"

64207;"counter: 7, thread: 0, process: 18194, request: GET /viewfeeds
HTTP/1.1,  time: Wed Nov 16 19:56:07 2011;"

64208;"counter: 8, thread: 0, process: 18194, request: GET /viewfeeds
HTTP/1.1,  time: Wed Nov 16 19:56:07 2011;"

64209;"counter: 9, thread: 0, process: 18194, request: GET
/viewfeeds/dosort&sortby=none HTTP/1.1,  time: Wed Nov 16 19:56:07 2011;"

64210;"counter: 10, thread: 0, process: 18194, request: GET
/viewfeeds/dosort&sortby=none HTTP/1.1,  time: Wed Nov 16 19:56:07 2011;"

64211;"counter: 1, thread: 0, process: 18201, request: GET
/misc/viewfeeds/images/sidebar_05.png HTTP/1.1,  time: Wed Nov 16 19:56:07
2011;"

64212;"counter: 2, thread: 0, process: 18201, request: GET
/misc/viewfeeds/images/sidebar_05.png HTTP/1.1,  time: Wed Nov 16 19:56:07
2011;"

64213;"counter: 11, thread: 0, process: 18194, request: GET /recordings
HTTP/1.1,  time: Wed Nov 16 19:56:08 2011;"

64214;"counter: 12, thread: 0, process: 18194, request: GET /recordings
HTTP/1.1,  time: Wed Nov 16 19:56:08 2011;"

64215;"counter: 13, thread: 0, process: 18194, request: GET /cop HTTP/1.1,
time: Wed Nov 16 19:56:09 2011;"

64216;"counter: 14, thread: 0, process: 18194, request: GET /cop HTTP/1.1,
time: Wed Nov 16 19:56:09 2011;"

64217;"counter: 15, thread: 0, process: 18194, request: GET /logout
HTTP/1.1,  time: Wed Nov 16 19:56:10 2011;"

64218;"counter: 16, thread: 0, process: 18194, request: GET /logout
HTTP/1.1,  time: Wed Nov 16 19:56:10 2011;"

64219;"counter: 17, thread: 0, process: 18194, request: GET / HTTP/1.1,
time: Wed Nov 16 19:56:11 2011;"

 

 

As you can see, the counter is incremented within the same process
correctly, but is not shared among different processes.  Sorry, for the
overly verbose message, but can anybody tell me how to fix the sharing of my
variable ctr so that it is shared among all process?

 

 

Respectfully,

Pranesh


RE: Apache shared memory implementation

Posted by Pranesh Vadhirajan <va...@teralogics.com>.
Thanks Sorin.  The program worked fine when I made the changes you
suggested(I had to change the last line to "++((int) *shm_base);").  Can I
employ the same idea when it comes to more complicated structures?  I will
be making my own implementation of a linked list as a shared memory
structure?  Suppose, that the list is declared as "list *my_list", can I
just call set_shared region like this: set_shared_region(&my_list) ? Would
this work?

-----Original Message-----
From: Sorin Manolache [mailto:sorinm@gmail.com] 
Sent: Wednesday, November 16, 2011 5:51 PM
To: modules-dev@httpd.apache.org
Subject: Re: Apache shared memory implementation

You have some problems with the pointers.

You should have

void *shm_base;

and then

set_shared_region(void **base) {
 ...
 *base = mmap(...);
 if (*base == MAP_FAILED) { ... }
 ...
}

set_shared_region(&shm_base);

and when you increment the counter, you do

++((int *)shm_base);

--
S

Re: Apache shared memory implementation

Posted by Sorin Manolache <so...@gmail.com>.
On Wed, Nov 16, 2011 at 21:03, Pranesh Vadhirajan
<va...@teralogics.com> wrote:
> Hello Everyone,
>
>      I am trying to understand how to implement sharing of objects in memory
> between various processes in apache.  I have been using the routines defined
> in <sys/mman.h> to implement the shared memory mapping functionality.
> However, I am not seeing any actual sharing of the objects in my output.
>
>
>
> I have attached the code segment of my module containing the request
> handler:
>
>
>
> #include "httpd.h"
>
> #include "http_core.h"
>
> #include "http_config.h"
>
> #include <stdlib.h>
>
> #include <time.h>
>
> #include <sys/time.h>
>
> #include <sys/types.h>
>
> #include "sessions.h"
>
> #include <regex.h>
>
> #include <stdio.h>
>
> #include <sys/mman.h>
>
> #include <sys/stat.h>
>
> #include <fcntl.h>
>
> #include <unistd.h>
>
>
>
>
>
> void set_shared_region(int *shared_int)
>
> {
>
>    int fd;
>
>
>
>    /* Create shared memory object and set its size */
>
>    fd = shm_open("/myregion", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
>
>    if(fd == -1)
>
>       fprintf(stderr,"shm_open error");
>
>
>
>    if(ftruncate(fd, sizeof(int)) == -1)
>
>        fprintf(stderr,"ftruncate error");
>
>
>
>     /* Map shared memory object */
>
>    shared_int = mmap(NULL, sizeof(int),PROT_READ | PROT_WRITE, MAP_SHARED,
> fd, 0);
>
>    if(shared_int == MAP_FAILED)
>
>       fprintf(stderr,"mmap error");
>
> }
>
>
>
> int start_mutex()
>
> {
>
>    if(initial_mutex_value == 0)
>
>    {
>
>       if(sem_init(&session_mutex,1,1) < 0)
>
>       {
>
>          fprintf(stderr,"error initializing semaphore");
>
>          return 0;
>
>       }
>
>       initial_mutex_value = 1;
>
>    }
>
>    return 1;
>
> }
>
>
>
> static int counter_handler(request_rec* r)
>
> {
>
>    char time_buffer[30];
>
>    char entry[1024];
>
>    long int tid,pid;
>
>    apr_ctime(time_buffer,r->request_time);
>
>    start_mutex();
>
>    sem_wait(&session_mutex);
>
>    set_shared_region(&ctr);
>
>    ctr++;
>
>    sem_post(&session_mutex);
>
>    //tid = (long int)getthreadid();
>
>    pid = (long int)getpid();
>
>    sprintf(entry,"counter: %i, thread: %ld, process: %ld, request: %s,
> time: %s;",ctr,(long int)0,pid,r->the_request,time_buffer);
>
>    tempToDB(entry);
>
>
>
>    return DECLINED;
>
> }
>
>
>
> static void counter_register_hooks (apr_pool_t *p)
>
> {
>
>    ap_hook_handler(counter_handler, NULL, NULL, APR_HOOK_REALLY_FIRST);
>
> }
>
>
>
> module AP_MODULE_DECLARE_DATA counter_module =
>
> {
>
>   STANDARD20_MODULE_STUFF,
>
>   NULL,//uvds_metrics_dir_conf,      /* Per-Directory Configuration */
>
>   NULL,//uvds_metrics_dir_merge,           /* Directory Config Merger */
>
>   NULL,//uvds_metrics_server_conf,         /* Per-Server Configuration */
>
>   NULL,//uvds_metrics_server_merge,  /* Server Config Merger */
>
>   NULL,//uvds_metrics_cmds,                /* Command Table (Directives) */
>
>   counter_register_hooks             /* Registering Hooks */
>
> };
>
>
>
> The handler code uses the variable ctr which is defined in the header file
> “sessions.h” .  Here’s the relevant segment in sessions.h:
>
>
>
>                                                 #include <stdio.h>
>
> #include <stdlib.h>
>
> #include <string.h>
>
> #include "libpq-fe.h"
>
> #include <semaphore.h>
>
>
>
> sem_t session_mutex;
>
> int initial_mutex_value = 0;
>
> int ctr = 0;
>
>
>
> void tempToDB(char *entry);
>
>
>
>
>
>
>
> Here’s the output of my code:
>
>
>
>                                                 64201;"counter: 1, thread:
> 0, process: 18194, request: POST /login?destination=login HTTP/1.1,  time:
> Wed Nov 16 19:56:04 2011;"
>
> 64202;"counter: 2, thread: 0, process: 18194, request: POST
> /login?destination=login HTTP/1.1,  time: Wed Nov 16 19:56:04 2011;"
>
> 64203;"counter: 3, thread: 0, process: 18194, request: GET /login HTTP/1.1,
> time: Wed Nov 16 19:56:05 2011;"
>
> 64204;"counter: 4, thread: 0, process: 18194, request: GET /login HTTP/1.1,
> time: Wed Nov 16 19:56:05 2011;"
>
> 64205;"counter: 5, thread: 0, process: 18194, request: GET /dashboard
> HTTP/1.1,  time: Wed Nov 16 19:56:06 2011;"
>
> 64206;"counter: 6, thread: 0, process: 18194, request: GET /dashboard
> HTTP/1.1,  time: Wed Nov 16 19:56:06 2011;"
>
> 64207;"counter: 7, thread: 0, process: 18194, request: GET /viewfeeds
> HTTP/1.1,  time: Wed Nov 16 19:56:07 2011;"
>
> 64208;"counter: 8, thread: 0, process: 18194, request: GET /viewfeeds
> HTTP/1.1,  time: Wed Nov 16 19:56:07 2011;"
>
> 64209;"counter: 9, thread: 0, process: 18194, request: GET
> /viewfeeds/dosort&sortby=none HTTP/1.1,  time: Wed Nov 16 19:56:07 2011;"
>
> 64210;"counter: 10, thread: 0, process: 18194, request: GET
> /viewfeeds/dosort&sortby=none HTTP/1.1,  time: Wed Nov 16 19:56:07 2011;"
>
> 64211;"counter: 1, thread: 0, process: 18201, request: GET
> /misc/viewfeeds/images/sidebar_05.png HTTP/1.1,  time: Wed Nov 16 19:56:07
> 2011;"
>
> 64212;"counter: 2, thread: 0, process: 18201, request: GET
> /misc/viewfeeds/images/sidebar_05.png HTTP/1.1,  time: Wed Nov 16 19:56:07
> 2011;"
>
> 64213;"counter: 11, thread: 0, process: 18194, request: GET /recordings
> HTTP/1.1,  time: Wed Nov 16 19:56:08 2011;"
>
> 64214;"counter: 12, thread: 0, process: 18194, request: GET /recordings
> HTTP/1.1,  time: Wed Nov 16 19:56:08 2011;"
>
> 64215;"counter: 13, thread: 0, process: 18194, request: GET /cop HTTP/1.1,
> time: Wed Nov 16 19:56:09 2011;"
>
> 64216;"counter: 14, thread: 0, process: 18194, request: GET /cop HTTP/1.1,
> time: Wed Nov 16 19:56:09 2011;"
>
> 64217;"counter: 15, thread: 0, process: 18194, request: GET /logout
> HTTP/1.1,  time: Wed Nov 16 19:56:10 2011;"
>
> 64218;"counter: 16, thread: 0, process: 18194, request: GET /logout
> HTTP/1.1,  time: Wed Nov 16 19:56:10 2011;"
>
> 64219;"counter: 17, thread: 0, process: 18194, request: GET / HTTP/1.1,
> time: Wed Nov 16 19:56:11 2011;"
>
>
>
>
>
> As you can see, the counter is incremented within the same process
> correctly, but is not shared among different processes.  Sorry, for the
> overly verbose message, but can anybody tell me how to fix the sharing of my
> variable ctr so that it is shared among all process?
>
>
>
>
>
> Respectfully,
>
> Pranesh

You have some problems with the pointers.

You should have

void *shm_base;

and then

set_shared_region(void **base) {
 ...
 *base = mmap(...);
 if (*base == MAP_FAILED) { ... }
 ...
}

set_shared_region(&shm_base);

and when you increment the counter, you do

++((int *)shm_base);

--
S

Re: Apache shared memory implementation

Posted by "William A. Rowe Jr." <wr...@rowe-clan.net>.
On 11/16/2011 2:03 PM, Pranesh Vadhirajan wrote:
>
> I am trying to understand how to implement sharing of objects in memory between various
> processes in apache. I have been using the routines defined in <sys/mman.h> to implement
> the shared memory mapping functionality. However, I am not seeing any actual sharing of
> the objects in my output.

Hi Pranesh; you are more likely to get help with this on a linux
developer forum, since there is nothing Apache specific here.

You might want to look at the httpd scoreboard implementation,
or better yet, mod_socache_shm.c in the new betas, none of which
use the linux/unix shm conventions.  These are all based on the
portability layer in APR, so that the shared objects work on
additional platforms.