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

相关推荐
牛奶咖啡1312 分钟前
从零到一使用Linux+Nginx+MySQL+PHP搭建的Web网站服务器架构环境——LNMP(上)
linux·lnmp·ngnix的源码安装部署·mysql的二进制文件安装部署·php源码的安装部署·记录并解决安装php的各种问题
清木!32 分钟前
数据仓库详解
笔记
软件测试很重要38 分钟前
UOS20系统安装与 SSH/XRDP 远程访问功能配置指南
linux·运维·ssh
对你无可奈何1 小时前
关于Ubuntu的 update造成的内核升级
运维·服务器·ubuntu
GanGuaGua2 小时前
Linux系统:线程的互斥和安全
linux·运维·服务器·c语言·c++·安全
lsnm2 小时前
【LINUX网络】IP——网络层
linux·服务器·网络·c++·网络协议·tcp/ip
不掰手腕2 小时前
在UnionTech OS Server 20 (统信UOS服务器版) 上离线安装PostgreSQL (pgsql) 数据库
linux·数据库·postgresql
Lynnxiaowen3 小时前
今天继续昨天的正则表达式进行学习
linux·运维·学习·正则表达式·云计算·bash
努力学习的小廉3 小时前
深入了解linux系统—— POSIX信号量
linux·运维·服务器
刘一说3 小时前
CentOS部署ELK Stack完整指南
linux·elk·centos