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 文件。

相关推荐
深蓝海拓13 小时前
PySide6从0开始学习的笔记(十六) 定时器QTimer
笔记·python·qt·学习·pyqt
北辰水墨13 小时前
【算法篇】单调栈的学习
c++·笔记·学习·算法·单调栈
_OP_CHEN13 小时前
【Linux系统编程】(十八)Linux 进程创建与终止进阶:等待机制与程序替换的底层密码
linux·服务器·操作系统·进程·进程等待·进程替换·exec函数族
未来之窗软件服务13 小时前
服务器运维(二十)服务器防护双雄:Fail2ban 与 CrowdSec 入门指南——东方仙盟炼气期
运维·服务器·东方仙盟
不染尘.13 小时前
TCP可靠传输和流量控制
服务器·网络·网络协议·计算机网络·tcp
航Hang*13 小时前
第3章:复习篇——第3节:数据查询与统计
数据库·笔记·sql·mysql
姚青&13 小时前
1、Linux 系统与 Shell 环境准备
linux·运维·服务器
Vin0sen13 小时前
无响应的状态码分析
linux
运维小斌13 小时前
ubuntu22.04.5配置ip并使用远程工具连接
linux·运维·网络·ubuntu
爬山算法13 小时前
Netty(29)如何实现基于Netty的长连接和推送通知?
运维·服务器·网络