设为首页 收藏本站
查看: 2055|回复: 0

[经验分享] Memcached源码阅读之服务器资源调整

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2014-3-19 13:26:03 | 显示全部楼层 |阅读模式
本篇博客作为Memcached源码分析的开篇,这次阅读的源码版本为:1.4.15,开源软件各个版本之间差异比较大,同学们学习时,记得核对版本。
memcached的main函数位于memcached.c文件中,从main函数启动之后,会初始化一些资源和申请一些服务器资源,如下面所示:
1 Core文件大小和进程打开文件个数限制的调整。
if (maxcore != 0)  
{  
    struct rlimit rlim_new;  
    //获取当前Core文件大小的配置值  
    if (getrlimit(RLIMIT_CORE, &rlim) == 0)  
    {  
                //变量初始化为无限制  
                rlim_new.rlim_cur = rlim_new.rlim_max = RLIM_INFINITY;  
        if (setrlimit(RLIMIT_CORE, &rlim_new) != 0)//如果设置失败  
        {  
            //变量初始化为当前值的最大值  
            rlim_new.rlim_cur = rlim_new.rlim_max = rlim.rlim_max;  
            (void) setrlimit(RLIMIT_CORE, &rlim_new);//重新进行设置  
        }  
    }  

        //再次确认Core文件允许的大小,如果当前的Core文件的大小为0,则不允许Core文件产生,和maxcore!=0不符,程序结束  
    if ((getrlimit(RLIMIT_CORE, &rlim) != 0) || rlim.rlim_cur == 0)  
    {  
        fprintf(stderr, "failed to ensure corefile creation\n");  
        exit(EX_OSERR);  
    }  
}  
//读取进程允许打开的文件数信息,读取失败,程序退出  
if (getrlimit(RLIMIT_NOFILE, &rlim) != 0)  
{  
    fprintf(stderr, "failed to getrlimit number of files\n");  
    exit(EX_OSERR);  
}  
else  
{       //按memcached启动时的指定的最大连接数进行设置  
    rlim.rlim_cur = settings.maxconns;  
    rlim.rlim_max = settings.maxconns;  
    if (setrlimit(RLIMIT_NOFILE, &rlim) != 0)  
    {  
        fprintf(stderr,  
                "failed to set rlimit for open files. Try starting as root or requesting smaller maxconns value.\n");  
        exit(EX_OSERR);  
    }  
}  
2 启动用户的选择。
//uid==0表示以root运行程序  
if (getuid() == 0 || geteuid() == 0)  
{       //以root运行程序,同时未指定新的用户名称  
        if (username == 0 || *username == '\0')  
    {  
        fprintf(stderr, "can't run as root without the -u switch\n");  
        exit(EX_USAGE);  
    }  
        //判断是否存在指定的用户名称  
        if ((pw = getpwnam(username)) == 0)  
    {  
        fprintf(stderr, "can't find the user %s to switch to\n", username);  
        exit(EX_NOUSER);  
    }  
        //按新的用户修改memcached的执行权限位  
        if (setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0)  
    {  
        fprintf(stderr, "failed to assume identity of user %s\n", username);  
        exit(EX_OSERR);  
    }  
}  
3 以daemon的方式启动,daemon的实现如下,该daemon没有进行2次fork,APUE上面也有说第二次fork不是必须的。
int daemonize(int nochdir, int noclose)  
{  
    int fd;  
    //首先fork一次  
    switch (fork()) {  
    case -1://fork失败,程序结束  
        return (-1);  
    case 0://子进程执行下面的流程  
        break;  
    default://父进程安全退出  
        _exit(EXIT_SUCCESS);  
    }  
    //setsid调用成功之后,返回新的会话的ID,调用setsid函数的进程成为新的会话的领头进程,并与其父进程的会话组和进程组脱离  
    if (setsid() == -1)  
        return (-1);  

    if (nochdir == 0) {  
        //进程的当前目录切换到根目录下,根目录是一直存在的,其他的目录就不保证  
        if(chdir("/") != 0) {  
            perror("chdir");  
            return (-1);  
        }  
    }  

    if (noclose == 0 && (fd = open("/dev/null", O_RDWR, 0)) != -1) {  
        if(dup2(fd, STDIN_FILENO) < 0) {//将标准输入重定向到/dev/null下  
            perror("dup2 stdin");  
            return (-1);  
        }  
        if(dup2(fd, STDOUT_FILENO) < 0) {//将标准输出重定向到/dev/null下  
            perror("dup2 stdout");  
            return (-1);  
        }  
        if(dup2(fd, STDERR_FILENO) < 0) {//将标准错误重定向到/dev/null下  
            perror("dup2 stderr");  
            return (-1);  
        }  

        if (fd > STDERR_FILENO) {  
            if(close(fd) < 0) {//大于2的描述符都可以关闭  
                perror("close");  
                return (-1);  
            }  
        }  
    }  
    return (0);  
}  
4 锁定内存,默认分配的内存都是虚拟内存,在程序执行过程中可以按需换出,如果内存充足的话,可以锁定内存,不让系统将该进程所持有的内存换出。
if (lock_memory)  
{  
#ifdef HAVE_MLOCKALL  
    int res = mlockall(MCL_CURRENT | MCL_FUTURE);  
    if (res != 0)  
    {  
        fprintf(stderr, "warning: -k invalid, mlockall() failed: %s\n",  
                strerror(errno));  
    }  
#else  
    fprintf(stderr,  
            "warning: -k invalid, mlockall() not supported on this platform.  proceeding without.\n");  
#endif  
}  
5 忽略PIPE信号,PIPE信号是当网络连接一端已经断开,这时发送数据,会进行RST的重定向,再次发送数据,会触发PIPE信号,而PIPE信号的默认动作是退出进程,所以需要忽略该信号。
if (sigignore(SIGPIPE) == -1)  
{  
    perror("failed to ignore SIGPIPE; sigaction");  
    exit(EX_OSERR);  
}  
6 保存daemon进程的进程id到文件中,这样便于控制程序,读取文件内容,即可得到进程ID。
if (pid_file != NULL)  
{  
    save_pid(pid_file);  
}  



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-15970-1-1.html 上篇帖子: Memcached源码阅读之初始化参数解析和配置建议 下篇帖子: memcache研究笔记 之 hashtable 服务器 资源
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表