• Linux高性能服务器编程——ch7笔记


    第7章 Linux服务器程序规范

    7.1 日志

    Linux提供rsyslogd守护进程接收用户进程输出的日志和内核日志。
    image.png
    应用程序使用syslog函数与rsyslogd守护进程通信。

    void syslog(int priority, const char* message, …);

    openlog函数:改变syslog的默认输出方式。
    setlogmask函数:设置syslog的日志掩码(日志过滤,使日志级别大于日志掩码的日志信息被系统忽略)。
    closelog函数:关闭日志功能。

    7.2 用户信息

    真实用户ID(UID)、有效用户ID(EUID)、真实组ID(GID)、有效组ID(EGID)。
    一个进程拥有两个用户ID:UID和EUID。EUID存在的目的是方便资源访问:它使得运行程序的用户拥有该程序的有效用户的权限。
    有效用户为root的进程称为特权进程。EGID的含义与EUID类似:给运行目标程序的组用户提供有效组的权限。

    #include 
    #include 
    
    int main(int argc, char *argv[])
    {
        uid_t uid = getuid();
        uid_t euid = geteuid();
    
        printf("userid is %d, effective userid is:%d \n", uid, euid);
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    进程的UID是启动程序的用户的ID,而EUID则是root账户(文件所有者)的ID。

    static bool switch_to_user( uid_t user_id, gid_t gp_id )
    {
        //先确保目标用户不是root
        if ( ( user_id == 0 ) && ( gp_id == 0 ) )
        {
            return false;
        }
    	//确保当前用户是合法用户:root或者目标用户
        gid_t gid = getgid();
        uid_t uid = getuid();
        if ( ( ( gid != 0 ) || ( uid != 0 ) ) && ( ( gid != gp_id ) || ( uid != user_id ) ) )
        {
            return false;
        }
    	//如果不是root,则已经是目标用户
        if ( uid != 0 )
        {
            return true;
        }
    	//切换到目标用户
        if ( ( setgid( gp_id ) < 0 ) || ( setuid( user_id ) < 0 ) )
        {
            return false;
        }
    
        return true;
    }
    
    • 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

    7.3 进程间关系

    每个进程都隶属于一个进程组,因此它们除了PID信息外,还有进程组ID(PGID)。
    每个进程组都有一个首领进程,其PGID和PID相同。进程组将一直存在,直到其中所有进程都退出,或者加入到其他进程组。
    一个进程只能设置自己或者其子进程的PGID,并且,当子进程调用exec系列函数后,也不能再在父进程中对它设置PGID。
    一些有关联的进程组将形成一个会话(session),通过setsid函数实现。调用进程成为会话的首领,新建一个进程组,其PGID就是调用进程的PID,调用进程成为该组的首领。调用进程将甩开终端。
    image.png

    7.4 系统资源限制

    物理设备限制(CPU 数量、内存数量等)、系统策略限制(CPU 时间等),以及具体实现的限制(比如文件名的最大长度)。
    getrlimit、setrlimit函数:读取和设置系统资源限制。

    7.5 改变工作目录和根目录

    getcwd函数:获取进程当前工作目录。
    chdir函数:改变进程工作目录。
    chroot函数:改变进程根目录。并不改变进程的当前工作目录,仍需要用chdir函数将工作目录切换至新的根目录。

    7.6 服务器程序后台化

    bool daemonize()
    {
        //创建子进程,关闭父进程,这样可以使程序在后台运行
        pid_t pid = fork();
        if (pid < 0)
            return false;
        else if (pid > 0)
            exit(0);
    	//设置文件权限掩码。当进程创建新文件(使用open(const char *pathname, int flags,
        // mode_t mode)系统调用)时,文件的权限将是 mode & 0777
        umask(0);
    	//创建新的会话,设置本进程为进程组的首领
        pid_t sid = setsid();
        if (sid < 0)
            return false;
    	//切换工作目录
        if ((chdir("/")) < 0)
            return false;
    	//关闭标准输入设备、标准输出设备和标准错误输出设备
        close(STDIN_FILENO);
        close(STDOUT_FILENO);
        close(STDERR_FILENO);
    	//关闭其他已经打开的文件描述符,代码省略
    	//将标准输入、标准输出和标准错误输出都定向到 /dev/null 文件
        open("/dev/null", O_RDONLY);
        open("/dev/null", O_RDWR);
        open("/dev/null", O_RDWR);
    
        return true;
    }
    
    • 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

    int daemon(int nochdir, int noclose);

    nochdir是否改变工作目录,noclose是否将标准输入、标准输出和标准错误输出都定向到 /dev/null 文件。

  • 相关阅读:
    【期末考试复习】概率论与数理统计(知识点模式 - 复习题1)(内容1)
    程序环境和预处理
    XXL-Job学习笔记
    MapReduce 论文
    redis缓存数据和表数据一致性之延时双删策略
    ORB-SLAM2 ---- computeOrbDescriptor函数
    2023第五届山东国际中医药产业展会,中医养生展,中医文化展
    python(27)反射机制
    成都瀚网科技有限公司:抖店怎么开通直播?
    NLP自然语言处理学习笔记(九)(转自咕泡AI)
  • 原文地址:https://blog.csdn.net/qq_43680965/article/details/133978113