共享内存的实现

Catalogue
  1. 1. 共享内存
  2. 2. 申请内存
  3. 3. 演示案例

共享内存

本质为通过系统调用申请一块内存,由系统调用,该内存可以跨进程间使用,有是那种共享内存的申请方式

    1. 采用mmap 方式申请共享内存
    1. 采用文件映射方式申请共享内存
    1. 采用 shmget 系统调用方式申请共享内存

上面三种方式在本次实验中分别对应三种宏

    1. HAVE_MAP_ANON
    1. HAVE_MAP_DEVZERO
    1. HAVE_SYSVSHM

      申请内存

      1
      2
      3
      4
      5
      6
      7
      8
      9
       //申请共享内存
      shm_t shm;
      size_t size;
      size = 8 * 16;//分配128字节内存
      shm.size = size;
      shm.name = (u_char *)"nginx_shared_zone";
      shm.server = serv;
      shm_alloc(&shm);
      int* count = (int *)(shm.addr + 8);
  • 上面的例子中,shm_alloc方法分配了 128字节内存

  • 申请成功后,shm.addr 即是共享的内存首地址,需要自己分配管理
  • int *count 截取了前8个字节分配使用。转换为8字节int指针使用,

    演示案例

    通过申请一块共享内存地址,分配一个int指针,模拟http多进程处理请求并统计请求总数.如下为请求样例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    static void eventloop(server *serv) {
    pid_t pid;
    struct sigaction sa;
    connection *con;
    //申请共享内存
    shm_t shm;
    size_t size;
    size = 8 * 16;//分配128字节内存
    shm.size = size;
    shm.name = (u_char *)"nginx_shared_zone";
    shm.server = serv;
    shm_alloc(&shm);
    int* count = (int *)(shm.addr + 8);

    sa.sa_handler = sigchld_handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART;

    if (sigaction(SIGCHLD, &sa, NULL) == -1) {
    perror("sigaction");
    exit(1);
    }

    while (1) {
    if ((con = connection_accept(serv)) == NULL) {
    continue;
    }

    if ((pid = fork()) == 0) {

    // 子进程中处理HTTP请求
    close(serv->sockfd);
    *count += 1;
    printf("request count is %d\n",*count);
    connection_handler(serv, con);
    connection_close(con);

    exit(0);
    }

    printf("child process: %d\n", pid);
    connection_close(con);
    }
    shm_free(&shm);
    }

统计结果:ab -c 10 -n 10 http://127.0.0.1:8080/

1
2
3
4
5
6
request count is 7
request count is 8
socket: 5
socket: 5
request count is 9
request count is 10