int main(int argc, char **argv) { parse_cmd(argc, argv); #ifdef HAVE_JEMALLOC if (jemalloc_limit) { memory_used_fn = jemalloc_size_allocated; } #endif if (!memory_used_fn) { memory_used_fn = zmalloc_used_memory; } zmalloc_enable_thread_safeness(); pthread_t threads[thread_count]; for (int i = 0; i < thread_count; i++) { if (0 != pthread_create(&threads[i], 0, thread_worker, 0)) { fprintf(stderr, "error while creating thread\n"); return -1; } } char size_human_buf[1024]; char rss_human_buf[1024]; for (;;) { sleep(1); size_t rss = zmalloc_get_rss(); size_t used = memory_used_fn(); mem_cpu_to_human(used, size_human_buf, 1024); mem_cpu_to_human(rss, rss_human_buf, 1024); printf("memory_used %s, rss %s, fragmentation ratio %f\n", size_human_buf, rss_human_buf, zmalloc_get_fragmentation_ratio(rss)); } return 0; }
int main (int argc, char **argv) { struct timeval tv; // 初始化相关环境变量与库 #ifdef INIT_SETPROCTITLE_REPLACEMENT spt_init(argc, argv); #endif // 设置当前的`locale`命令里的内容 setlocale(LC_COLLATE, ""); // 自动分配线程安全 zmalloc_enable_thread_safeness(); // 设置自动分配函数句柄(out of memory) zmalloc_set_oom_handler(redisOutOfMemoryHandler); // 时间异或pid生成随机数种子 srand(time(NULL) ^ getpid()); gettimeofday(&tv, NULL); // 设置字典hash值种子 dictSetHashFunctionSeed(tv.tv_sec ^ tv.tv_usec ^ getpid()); // 定点模式检测 server.sentinel_mode = checkForSentinelMode(argc, argv); // 初始化服务配置 initServerConfig(); // 定点模式处理 if (server.sentinel_mode) { printf("deal with sentinel mode\n"); } if (argc >= 2) { int j = 1; // init empty string sds options = sdsempty(); char *configfile = NULL; if (strcmp(argv[1], "-v") == 0 || strcmp(argv[1], "--version") == 0) version(); if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) usage(); if (strcmp(argv[1], "--test-memory") == 0) { if (argc == 3) { // 内存测试还未完全写完 memtest(atoi(argv[2]), 50); exit(0); } else { fprintf(stderr, "Please specify the amount of memory to test in megabytes.\n"); fprintf(stderr, "Example: ./redis-server --test-memory 4096\n\n"); exit(1); } } /* * 第一个参数为'--'开头, j始终为1 * 第一个参数不为'--'开头, j始终为2 * */ // j为1,第1个参数不是'--'开头的是配置文件 if (argv[j][0] != '-' || argv[j][1] != '-') { configfile = argv[j++]; } // 配置文件参数后还有内容 while (j != argc) { // 所有参数有包括'--'开头的参数 if (argv[j][0] == '-' && argv[j][1] == '-') { if (sdslen(options)) options = sdscat(options, "\n"); options = sdscat(options, " "); } else { // append new string, 转义特殊字符, return new pointer options = sdscatrepr(options, argv[j], strlen(argv[j])); options = sdscat(options, " "); } j++; } if (server.sentinel_mode && configfile && *configfile == '-') { printf("need redis log\n"); exit(1); } if (configfile) { server.configfile = getAbsolutePath(configfile); } resetServerSaveParams(); loadServerConfig(configfile, options); sdsfree(options); } else { printf("warning: no config file specified\n"); } // 后台模式 if (server.daemonize) { daemonize(); } // init server initServer(); printf("redis done\n"); return 0; }
void vmInit(void) { off_t totsize; int pipefds[2]; size_t stacksize; struct flock fl; if (server.vm_max_threads != 0) zmalloc_enable_thread_safeness(); /* we need thread safe zmalloc() */ redisLog(REDIS_NOTICE,"Using '%s' as swap file",server.vm_swap_file); /* Try to open the old swap file, otherwise create it */ if ((server.vm_fp = fopen(server.vm_swap_file,"r+b")) == NULL) { server.vm_fp = fopen(server.vm_swap_file,"w+b"); } if (server.vm_fp == NULL) { redisLog(REDIS_WARNING, "Can't open the swap file: %s. Exiting.", strerror(errno)); exit(1); } server.vm_fd = fileno(server.vm_fp); /* Lock the swap file for writing, this is useful in order to avoid * another instance to use the same swap file for a config error. */ fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; fl.l_start = fl.l_len = 0; if (fcntl(server.vm_fd,F_SETLK,&fl) == -1) { redisLog(REDIS_WARNING, "Can't lock the swap file at '%s': %s. Make sure it is not used by another Redis instance.", server.vm_swap_file, strerror(errno)); exit(1); } /* Initialize */ server.vm_next_page = 0; server.vm_near_pages = 0; server.vm_stats_used_pages = 0; server.vm_stats_swapped_objects = 0; server.vm_stats_swapouts = 0; server.vm_stats_swapins = 0; totsize = server.vm_pages*server.vm_page_size; redisLog(REDIS_NOTICE,"Allocating %lld bytes of swap file",totsize); if (ftruncate(server.vm_fd,totsize) == -1) { redisLog(REDIS_WARNING,"Can't ftruncate swap file: %s. Exiting.", strerror(errno)); exit(1); } else { redisLog(REDIS_NOTICE,"Swap file allocated with success"); } server.vm_bitmap = zcalloc((server.vm_pages+7)/8); redisLog(REDIS_VERBOSE,"Allocated %lld bytes page table for %lld pages", (long long) (server.vm_pages+7)/8, server.vm_pages); /* Initialize threaded I/O (used by Virtual Memory) */ server.io_newjobs = listCreate(); server.io_processing = listCreate(); server.io_processed = listCreate(); server.io_ready_clients = listCreate(); pthread_mutex_init(&server.io_mutex,NULL); pthread_mutex_init(&server.io_swapfile_mutex,NULL); server.io_active_threads = 0; if (pipe(pipefds) == -1) { redisLog(REDIS_WARNING,"Unable to intialized VM: pipe(2): %s. Exiting." ,strerror(errno)); exit(1); } server.io_ready_pipe_read = pipefds[0]; server.io_ready_pipe_write = pipefds[1]; redisAssert(anetNonBlock(NULL,server.io_ready_pipe_read) != ANET_ERR); /* LZF requires a lot of stack */ pthread_attr_init(&server.io_threads_attr); pthread_attr_getstacksize(&server.io_threads_attr, &stacksize); /* Solaris may report a stacksize of 0, let's set it to 1 otherwise * multiplying it by 2 in the while loop later will not really help ;) */ if (!stacksize) stacksize = 1; while (stacksize < REDIS_THREAD_STACK_SIZE) stacksize *= 2; pthread_attr_setstacksize(&server.io_threads_attr, stacksize); /* Listen for events in the threaded I/O pipe */ if (aeCreateFileEvent(server.el, server.io_ready_pipe_read, AE_READABLE, vmThreadedIOCompletedJob, NULL) == AE_ERR) oom("creating file event"); }
void vmInit(void) { off totsize; int pipefds[2]; size_t stacksize; #ifndef _WIN32 struct flock fl; #endif if (server.vm_max_threads != 0) zmalloc_enable_thread_safeness(); /* we need thread safe zmalloc() */ redisLog(REDIS_NOTICE,"Using '%s' as swap file",server.vm_swap_file); /* Try to open the old swap file, otherwise create it */ if ((server.vm_fp = fopen(server.vm_swap_file,"r+b")) == NULL) { server.vm_fp = fopen(server.vm_swap_file,"w+b"); } if (server.vm_fp == NULL) { redisLog(REDIS_WARNING, "Can't open the swap file: %s. Exiting.", strerror(errno)); exit(1); } server.vm_fd = fileno(server.vm_fp); /* Lock the swap file for writing, this is useful in order to avoid * another instance to use the same swap file for a config error. */ #ifdef _WIN32 // LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0) if(!LockFile((HANDLE) _get_osfhandle(server.vm_fd), (0x40000001), 0, 1, 0) ) { redisLog(REDIS_WARNING, "Can't lock the swap file at '%s': %s. Make sure it is not used by another Redis instance.", server.vm_swap_file, strerror(errno)); WSACleanup(); exit(1); } #else fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; fl.l_start = fl.l_len = 0; if (fcntl(server.vm_fd,F_SETLK,&fl) == -1) { redisLog(REDIS_WARNING, "Can't lock the swap file at '%s': %s. Make sure it is not used by another Redis instance.", server.vm_swap_file, strerror(errno)); exit(1); } #endif /* Initialize */ server.vm_next_page = 0; server.vm_near_pages = 0; server.vm_stats_used_pages = 0; server.vm_stats_swapped_objects = 0; server.vm_stats_swapouts = 0; server.vm_stats_swapins = 0; totsize = server.vm_pages*server.vm_page_size; #ifdef _WIN32 redisLog(REDIS_NOTICE,"Allocating %lld bytes of swap file",(long long) totsize); #else redisLog(REDIS_NOTICE,"Allocating %lld bytes of swap file",totsize); #endif if (ftruncate(server.vm_fd,totsize) == -1) { redisLog(REDIS_WARNING,"Can't ftruncate swap file: %s. Exiting.", strerror(errno)); exit(1); } else { redisLog(REDIS_NOTICE,"Swap file allocated with success"); } server.vm_bitmap = zcalloc((server.vm_pages+7)/8); redisLog(REDIS_VERBOSE,"Allocated %lld bytes page table for %lld pages", (long long) (server.vm_pages+7)/8, server.vm_pages); /* Initialize threaded I/O (used by Virtual Memory) */ server.io_newjobs = listCreate(); server.io_processing = listCreate(); server.io_processed = listCreate(); server.io_ready_clients = listCreate(); #ifndef _WIN32 /* moved to InitSharedObjecsts since they are first time used there */ pthread_mutex_init(&server.io_mutex,NULL); pthread_mutex_init(&server.io_swapfile_mutex,NULL); #endif server.io_active_threads = 0; if (pipe(pipefds) == -1) { redisLog(REDIS_WARNING,"Unable to intialized VM: pipe(2): %s. Exiting." ,strerror(errno)); exit(1); } server.io_ready_pipe_read = pipefds[0]; server.io_ready_pipe_write = pipefds[1]; #ifndef _WIN32 /* Windows distincts pipe and socket destriptors */ /* We will use blocking pipe, with peek before blocking read */ redisAssert(anetNonBlock(NULL,server.io_ready_pipe_read) != ANET_ERR); #endif /* LZF requires a lot of stack */ pthread_attr_init(&server.io_threads_attr); pthread_attr_getstacksize(&server.io_threads_attr, &stacksize); /* Solaris may report a stacksize of 0, let's set it to 1 otherwise * multiplying it by 2 in the while loop later will not really help ;) */ if (!stacksize) stacksize = 1; while (stacksize < REDIS_THREAD_STACK_SIZE) stacksize *= 2; pthread_attr_setstacksize(&server.io_threads_attr, stacksize); /* Listen for events in the threaded I/O pipe */ #ifdef _WIN32 /* Windows fix: need to pass flag that notifies Api that file descriptor is pipe */ if (aeCreateFileEvent(server.el, server.io_ready_pipe_read, AE_READABLE | AE_PIPE, vmThreadedIOCompletedJob, NULL) == AE_ERR) oom("creating file event"); #else if (aeCreateFileEvent(server.el, server.io_ready_pipe_read, AE_READABLE, vmThreadedIOCompletedJob, NULL) == AE_ERR) oom("creating file event"); #endif }
int main(int argc, char *argv[]) { struct configOption *confOpt; char tmpstr[ALLOW_PATH_SIZE] = {""}; pthread_t ntid; g_logdir = NULL; g_logF = stderr; g_logFInt = STDERR_FILENO; setlocale(LC_ALL,""); zmalloc_enable_thread_safeness(); snprintf(tmpstr, ALLOW_PATH_SIZE, "%s/../", argv[0]); if (NULL == realpath(tmpstr, g_basedir)) { trvExit(0, "获取当前路径失败"); } g_conf = initConfig(); snprintf(tmpstr, ALLOW_PATH_SIZE, "%s/../conf/default.conf", g_basedir); configRead(g_conf, tmpstr); if (argc > 1) configRead(g_conf, argv[1]); /* argv[1] 是配置文件路径 */ if (NULL == g_conf->contents) { trvExit(0, "请选择配置文件"); } confOpt = configGet(g_conf, "log", "dir"); if (confOpt) { g_logdir = (char *)zmalloc(confOpt->valueLen+1); memcpy(g_logdir, confOpt->value, confOpt->valueLen); g_logdir[confOpt->valueLen] = 0x00; g_logF = fopen(g_logdir, "a+"); g_logFInt = fileno(g_logF); } signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); setupSignalHandlers(); /** * 主线程睡眠,等待网络就绪 * 单独开一个线程处理网路 */ pthread_mutex_lock(&g_rootThreadMutex); pthread_create(&ntid, NULL, _NTInit, NULL); pthread_cond_wait(&g_rootThreadCond, &g_rootThreadMutex); pthread_mutex_unlock(&g_rootThreadMutex); _STInitPlanet(NULL); /* 主线程睡眠,避免退出进程 */ pthread_cond_wait(&g_rootThreadCond, &g_rootThreadMutex); pthread_mutex_unlock(&g_rootThreadMutex); return 0; }