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

第7章 Linux服务器程序规范

7.1 日志

Linux提供rsyslogd守护进程接收用户进程输出的日志和内核日志。

应用程序使用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类似:给运行目标程序的组用户提供有效组的权限。

cpp 复制代码
#include <unistd.h>
#include <stdio.h>

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;
}

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

cpp 复制代码
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;
}

7.3 进程间关系

每个进程都隶属于一个进程组,因此它们除了PID信息外,还有进程组ID(PGID)。

每个进程组都有一个首领进程,其PGID和PID相同。进程组将一直存在,直到其中所有进程都退出,或者加入到其他进程组。

一个进程只能设置自己或者其子进程的PGID,并且,当子进程调用exec系列函数后,也不能再在父进程中对它设置PGID。

一些有关联的进程组将形成一个会话(session),通过setsid函数实现。调用进程成为会话的首领,新建一个进程组,其PGID就是调用进程的PID,调用进程成为该组的首领。调用进程将甩开终端。

7.4 系统资源限制

物理设备限制(CPU 数量、内存数量等)、系统策略限制(CPU 时间等),以及具体实现的限制(比如文件名的最大长度)。

getrlimit、setrlimit函数:读取和设置系统资源限制。

7.5 改变工作目录和根目录

getcwd函数:获取进程当前工作目录。

chdir函数:改变进程工作目录。

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

7.6 服务器程序后台化

cpp 复制代码
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;
}

int daemon(int nochdir, int noclose);

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

相关推荐
码农的小菜园2 小时前
gradle常用指令使用笔记
笔记
林姜泽樾2 小时前
Linux入门第十二章,创建用户、用户组、主组附加组等相关知识详解
linux·运维·服务器·centos
xiaokangzhe2 小时前
Linux系统安全
linux·运维·系统安全
feng一样的男子3 小时前
NFS 扩展属性 (xattr) 提示操作不支持解决方案
linux·go
南棱笑笑生3 小时前
20260310在瑞芯微原厂RK3576的Android14查看系统休眠时间
服务器·网络·数据库·rockchip
鸟电波3 小时前
硬件笔记——示波器篇
笔记
Don.TIk3 小时前
SpringCloud学习笔记
笔记·学习·spring cloud
XDHCOM3 小时前
ORA-32152报错咋整啊,数据库操作遇到null number问题远程帮忙修复
服务器·数据库·oracle
Highcharts.js3 小时前
Highcharts React v4.2.1 正式发布:更自然的React开发体验,更清晰的数据处理
linux·运维·javascript·ubuntu·react.js·数据可视化·highcharts
c++之路4 小时前
Linux网络协议与编程基础:TCP/IP协议族全解析
linux·网络协议·tcp/ip