MEMCACHED源碼之main初始化

一.啓動memcached
1.memcached啓動選項:
-p TCP監聽端口 (default: 11211)
-U UDP 監聽端口 (default: 11211, 0 is off)
-s UNIX socket監聽路徑,不支持網絡
-a UNIX socket訪問掩碼, 八進制 (default: 0700)
-l <ip_addr> 監聽的服務器IP地址 (default: all addresses)
-d 啓動一個守護進程
-r 最大限度利用核心文件限制
-u 運行memcached用戶
-m 最大的內存使用 (default: 64 MB)
-M 內存耗盡返回錯誤
-c 最大併發連接 (default: 1024)
-k 鎖定所有分頁內存
-v 輸出警告和錯誤信息
-vv 同時打印客戶端請求和返回信息
-vvv 打印內部狀態轉換信息
-i 打印memcached 和 libevent 版本信息
-P 設置保存pid文件, only used with -d option
-f 塊大小增長倍數 (default: 1.25)
-n key+value+flags最小分配空間(default: 48)
-L 如何有效,嘗試使用大內存頁。增加內存頁大小可以減少失誤的TLB數量,提高性能。
-D 指定key和IDs的分隔符 default is ":" (colon). 如果指定此選項,統計信息收集自動開啓;
-t 使用的線程數量 (default: 4)
-R 每個事件的最大請求數 (default: 20)
-C 禁止使用 CAS
-b 設置積壓隊列數限制 (default: 1024)
-B 綁定協議 - one of ascii, binary, or auto (default)
-I 分配給每個slab頁(default: 1mb, min: 1k, max: 128m)

2.啓動
# ./memcached -d -m 500 -u root -l 192.168.50.10 -p 12000 -c 256 -P /tmp/memcached.pid -vvv
slab class 1: chunk size 96 perslab 10922
slab class 2: chunk size 120 perslab 8738
slab class 3: chunk size 152 perslab 6898
slab class 4: chunk size 192 perslab 5461
slab class 5: chunk size 240 perslab 4369
slab class 6: chunk size 304 perslab 3449
slab class 7: chunk size 384 perslab 2730
slab class 8: chunk size 480 perslab 2184
slab class 9: chunk size 600 perslab 1747
slab class 10: chunk size 752 perslab 1394
slab class 11: chunk size 944 perslab 1110
slab class 12: chunk size 1184 perslab 885
slab class 13: chunk size 1480 perslab 708
slab class 14: chunk size 1856 perslab 564
slab class 15: chunk size 2320 perslab 451
slab class 16: chunk size 2904 perslab 361
slab class 17: chunk size 3632 perslab 288
slab class 18: chunk size 4544 perslab 230
slab class 19: chunk size 5680 perslab 184
slab class 20: chunk size 7104 perslab 147
slab class 21: chunk size 8880 perslab 118
slab class 22: chunk size 11104 perslab 94
slab class 23: chunk size 13880 perslab 75
slab class 24: chunk size 17352 perslab 60
slab class 25: chunk size 21696 perslab 48
slab class 26: chunk size 27120 perslab 38
slab class 27: chunk size 33904 perslab 30
slab class 28: chunk size 42384 perslab 24
slab class 29: chunk size 52984 perslab 19
slab class 30: chunk size 66232 perslab 15
slab class 31: chunk size 82792 perslab 12
slab class 32: chunk size 103496 perslab 10
slab class 33: chunk size 129376 perslab 8
slab class 34: chunk size 161720 perslab 6
slab class 35: chunk size 202152 perslab 5
slab class 36: chunk size 252696 perslab 4
slab class 37: chunk size 315872 perslab 3
slab class 38: chunk size 394840 perslab 2
slab class 39: chunk size 493552 perslab 2
slab class 40: chunk size 616944 perslab 1
slab class 41: chunk size 771184 perslab 1
slab class 42: chunk size 1048576 perslab 1
使用12000端口,root用戶,最大使用500M內存,253個併發連接,輸出詳細信息,以守護進程方式運行。
從輸出信息可看出memcached分配內存的過程。

在入口main中 初始化階段 while循環 接受處理這些參數:

int main (int argc, char **argv) {
    .....若干變量聲明....

    if (!sanitycheck()) {
        return EX_OSERR;
    }

    /* handle SIGINT */
    signal(SIGINT, sig_handler);

    /* init settings */
    settings_init();

    /* set stderr non-buffering (for running under, say, daemontools) */
    setbuf(stderr, NULL);

    /* process arguments */     /* arguments 後不跟值  arguments: 後跟值 */
    while (-1 != (c = getopt(argc, argv,
          "a:"  /* access mask for unix socket */   /* UNIX socket訪問掩碼, 八進制 (default: 0700) */
          "A"  /* enable admin shutdown commannd */
          "p:"  /* TCP port number to listen on */  /* TCP監聽端口 (default: 11211) */
          "s:"  /* unix socket path to listen on */ /* UNIX socket監聽路徑, 不支持網絡 */
          "U:"  /* UDP port number to listen on */  /* UDP監聽端口 (default: 11211, 0 is off) */
          "m:"  /* max memory to use for items in megabytes */  /* 最大的內存使用 (default: 64 MB) */
          "M"   /* return error on memory exhausted */  /* 內存耗盡返回錯誤 */
          "c:"  /* max simultaneous connections */  /* 最大併發連接 (default: 1024) */
          "k"   /* lock down all paged memory */    /* 鎖定所有分頁內存 */
          "hi"  /* help, licence info */
          "r"   /* maximize core file limit */      /* 最大限度利用核心文件限制 */
          "v"   /* verbose */                       /* 輸出警告和錯誤信息 */
          "d"   /* daemon mode */                   /* 啓動一個守護進程 */
          "l:"  /* interface to listen on */        /* <ip_addr> 監聽的服務器IP地址 (default: all addresses) */
          "u:"  /* user identity to run as */       /* 運行memcached用戶 */
          "P:"  /* save PID in file */              /* 設置保存pid文件, only used with -d option */
          "f:"  /* factor? */                       /* 塊大小增長倍數 (default: 1.25) */
          "n:"  /* minimum space allocated for key+value+flags */   /* key+value+flags最小分配空間(default: 48) */
          "t:"  /* threads */                       /* 使用的線程數量 (default: 4) */
          "D:"  /* prefix delimiter? */             /* 指定key和IDs的分隔符 default is ":" (colon). 如果指定此選項,統計信息收集自動開啓; */
          "L"   /* Large memory pages */            /* 如何有效,嘗試使用大內存頁。增加內存頁大小可以減少失誤的TLB數量,提高性能。 */
          "R:"  /* max requests per event */        /* 每個事件的最大請求數 (default: 20) */
          "C"   /* Disable use of CAS */            /* 禁止使用 CAS */
          "b:"  /* backlog queue limit */           /* 設置積壓隊列數限制 (default: 1024) */
          "B:"  /* Binding protocol */              /* 綁定協議 - one of ascii, binary, or auto (default) */
          "I:"  /* Max item size */                 /* 分配給每個slab頁(default: 1mb, min: 1k, max: 128m) */
          "S"   /* Sasl ON */
          "F"   /* Disable flush_all */
          "o:"  /* Extended generic options */
        ))) {
        switch (c) {
        case 'A':
            /* enables "shutdown" command */
            settings.shutdown_command = true;
            break;

        case 'a':
            /* access for unix domain socket, as octal mask (like chmod)*/
            settings.access= strtol(optarg,NULL,8);
            break;

        case 'U':
            /* UDP port number to listen on */
            settings.udpport = atoi(optarg);
            udp_specified = true;
            break;
        case 'p':
            /* TCP port number to listen on */
            settings.port = atoi(optarg);
            tcp_specified = true;
            break;
        case 's':
            /* unix socket path to listen on */
            settings.socketpath = optarg;
            break;
        case 'm':
            /* max memory to use for items in megabytes */
            settings.maxbytes = ((size_t)atoi(optarg)) * 1024 * 1024;
            break;
        case 'M':
            /* return error on memory exhausted */
            settings.evict_to_free = 0;
            break;
        case 'c':
            /* max simultaneous connections */
            settings.maxconns = atoi(optarg);
            break;
        case 'h':
            /* help, licence info */
            usage();
            exit(EXIT_SUCCESS);
        case 'i':
            /* help, licence info */
            usage_license();
            exit(EXIT_SUCCESS);
        case 'k':
            /* lock down all paged memory */ 
            lock_memory = true;
            break;
        case 'v':
            /* verbose */
            settings.verbose++;
            break;
        case 'l':
            /* interface to listen on */
            if (settings.inter != NULL) {
                size_t len = strlen(settings.inter) + strlen(optarg) + 2;
                char *p = malloc(len);
                if (p == NULL) {
                    fprintf(stderr, "Failed to allocate memory\n");
                    return 1;
                }
                snprintf(p, len, "%s,%s", settings.inter, optarg);
                free(settings.inter);
                settings.inter = p;
            } else {
                settings.inter= strdup(optarg);
            }
            break;
        case 'd':
            do_daemonize = true;
            break;
        case 'r':
            maxcore = 1;
            break;
        case 'R':
            settings.reqs_per_event = atoi(optarg);
            if (settings.reqs_per_event == 0) {
                fprintf(stderr, "Number of requests per event must be greater than 0\n");
                return 1;
            }
            break;
        case 'u':
            /* user identity to run as */
            username = optarg;
            break;
        case 'P':
            pid_file = optarg;
            break;
        case 'f':
            settings.factor = atof(optarg);
            if (settings.factor <= 1.0) {
                fprintf(stderr, "Factor must be greater than 1\n");
                return 1;
            }
            break;
        case 'n':
            settings.chunk_size = atoi(optarg);
            if (settings.chunk_size == 0) {
                fprintf(stderr, "Chunk size must be greater than 0\n");
                return 1;
            }
            break;
        case 't':
            settings.num_threads = atoi(optarg);
            if (settings.num_threads <= 0) {
                fprintf(stderr, "Number of threads must be greater than 0\n");
                return 1;
            }
            /* There're other problems when you get above 64 threads.
             * In the future we should portably detect # of cores for the
             * default.
             */
            if (settings.num_threads > 64) {
                fprintf(stderr, "WARNING: Setting a high number of worker"
                                "threads is not recommended.\n"
                                " Set this value to the number of cores in"
                                " your machine or less.\n");
            }
            break;
        case 'D':
            if (! optarg || ! optarg[0]) {
                fprintf(stderr, "No delimiter specified\n");
                return 1;
            }
            settings.prefix_delimiter = optarg[0];
            settings.detail_enabled = 1;
            break;
        case 'L' :
            if (enable_large_pages() == 0) {
                preallocate = true;
            } else {
                fprintf(stderr, "Cannot enable large pages on this system\n"
                    "(There is no Linux support as of this version)\n");
                return 1;
            }
            break;
        case 'C' :
            settings.use_cas = false;
            break;
        case 'b' :
            settings.backlog = atoi(optarg);
            break;
        case 'B':
            protocol_specified = true;
            if (strcmp(optarg, "auto") == 0) {
                settings.binding_protocol = negotiating_prot;
            } else if (strcmp(optarg, "binary") == 0) {
                settings.binding_protocol = binary_prot;
            } else if (strcmp(optarg, "ascii") == 0) {
                settings.binding_protocol = ascii_prot;
            } else {
                fprintf(stderr, "Invalid value for binding protocol: %s\n"
                        " -- should be one of auto, binary, or ascii\n", optarg);
                exit(EX_USAGE);
            }
            break;
        case 'I':
            buf = strdup(optarg);
            unit = buf[strlen(buf)-1];
            if (unit == 'k' || unit == 'm' ||
                unit == 'K' || unit == 'M') {
                buf[strlen(buf)-1] = '\0';
                size_max = atoi(buf);
                if (unit == 'k' || unit == 'K')
                    size_max *= 1024;
                if (unit == 'm' || unit == 'M')
                    size_max *= 1024 * 1024;
                settings.item_size_max = size_max;
            } else {
                settings.item_size_max = atoi(buf);
            }
            if (settings.item_size_max < 1024) {
                fprintf(stderr, "Item max size cannot be less than 1024 bytes.\n");
                return 1;
            }
            if (settings.item_size_max > 1024 * 1024 * 128) {
                fprintf(stderr, "Cannot set item size limit higher than 128 mb.\n");
                return 1;
            }
            if (settings.item_size_max > 1024 * 1024) {
                fprintf(stderr, "WARNING: Setting item max size above 1MB is not"
                    " recommended!\n"
                    " Raising this limit increases the minimum memory requirements\n"
                    " and will decrease your memory efficiency.\n"
                );
            }
            free(buf);
            break;
        case 'S': /* set Sasl authentication to true. Default is false */
#ifndef ENABLE_SASL
            fprintf(stderr, "This server is not built with SASL support.\n");
            exit(EX_USAGE);
#endif
            settings.sasl = true;
            break;
       case 'F' :
            settings.flush_enabled = false;
            break;
        case 'o': /* It's sub-opts time! */
            subopts = optarg;

            while (*subopts != '\0') {

            switch (getsubopt(&subopts, subopts_tokens, &subopts_value)) {
            case MAXCONNS_FAST:
                settings.maxconns_fast = true;
                break;
            case HASHPOWER_INIT:
                if (subopts_value == NULL) {
                    fprintf(stderr, "Missing numeric argument for hashpower\n");
                    return 1;
                }
                settings.hashpower_init = atoi(subopts_value);
                if (settings.hashpower_init < 12) {
                    fprintf(stderr, "Initial hashtable multiplier of %d is too low\n",
                        settings.hashpower_init);
                    return 1;
                } else if (settings.hashpower_init > 64) {
                    fprintf(stderr, "Initial hashtable multiplier of %d is too high\n"
                        "Choose a value based on \"STAT hash_power_level\" from a running instance\n",
                        settings.hashpower_init);
                    return 1;
                }
                break;
            case SLAB_REASSIGN:
                settings.slab_reassign = true;
                break;
            case SLAB_AUTOMOVE:
                if (subopts_value == NULL) {
                    settings.slab_automove = 1;
                    break;
                }
                settings.slab_automove = atoi(subopts_value);
                if (settings.slab_automove < 0 || settings.slab_automove > 2) {
                    fprintf(stderr, "slab_automove must be between 0 and 2\n");
                    return 1;
                }
                break;
            case TAIL_REPAIR_TIME:
                if (subopts_value == NULL) {
                    fprintf(stderr, "Missing numeric argument for tail_repair_time\n");
                    return 1;
                }
                settings.tail_repair_time = atoi(subopts_value);
                if (settings.tail_repair_time < 10) {
                    fprintf(stderr, "Cannot set tail_repair_time to less than 10 seconds\n");
                    return 1;
                }
                break;
            case HASH_ALGORITHM:
                if (subopts_value == NULL) {
                    fprintf(stderr, "Missing hash_algorithm argument\n");
                    return 1;
                };
                if (strcmp(subopts_value, "jenkins") == 0) {
                    hash_type = JENKINS_HASH;
                } else if (strcmp(subopts_value, "murmur3") == 0) {
                    hash_type = MURMUR3_HASH;
                } else {
                    fprintf(stderr, "Unknown hash_algorithm option (jenkins, murmur3)\n");
                    return 1;
                }
                break;
            case LRU_CRAWLER:
                if (start_item_crawler_thread() != 0) {
                    fprintf(stderr, "Failed to enable LRU crawler thread\n");
                    return 1;
                }
                break;
            case LRU_CRAWLER_SLEEP:
                settings.lru_crawler_sleep = atoi(subopts_value);
                if (settings.lru_crawler_sleep > 1000000 || settings.lru_crawler_sleep < 0) {
                    fprintf(stderr, "LRU crawler sleep must be between 0 and 1 second\n");
                    return 1;
                }
                break;
            case LRU_CRAWLER_TOCRAWL:
                if (!safe_strtoul(subopts_value, &tocrawl)) {
                    fprintf(stderr, "lru_crawler_tocrawl takes a numeric 32bit value\n");
                    return 1;
                }
                settings.lru_crawler_tocrawl = tocrawl;
                break;
            default:
                printf("Illegal suboption \"%s\"\n", subopts_value);
                return 1;
            }

            }
            break;
        default:
            fprintf(stderr, "Illegal argument \"%c\"\n", c);
            return 1;
        }
    }


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章