Linux高性能服务器编程|阅读笔记:第7章 - Linux服务器程序规范

举报
海轰Pro 发表于 2023/05/22 21:41:50 2023/05/22
【摘要】 简介Hello!非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出~ ଘ(੭ˊᵕˋ)੭昵称:海轰标签:程序猿|C++选手|学生简介:因C语言结识编程,随后转入计算机专业,获得过国家奖学金,有幸在竞赛中拿过一些国奖、省奖…已保研学习经验:扎实基础 + 多做笔记 + 多敲代码 + 多思考 + 学好英语! 唯有努力💪 本文仅记录自己感兴趣的内容 7.1 日志 7.1.1 Linux系统...

简介

Hello!
非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出~
 
ଘ(੭ˊᵕˋ)੭
昵称:海轰
标签:程序猿|C++选手|学生
简介:因C语言结识编程,随后转入计算机专业,获得过国家奖学金,有幸在竞赛中拿过一些国奖、省奖…已保研
学习经验:扎实基础 + 多做笔记 + 多敲代码 + 多思考 + 学好英语!
 
唯有努力💪
 
本文仅记录自己感兴趣的内容

7.1 日志

7.1.1 Linux系统日志

linux提供一个守护进程来处理系统日志:rsyslogd

rsyslogd守护进程既能接收用户进程输出的日志,又能接收内核日志

用户进程是通过调用syslog函数生成系统日志的

该函数将日志输出道一个UNIX本地域socket类型的文件/dec/log中
rsyslogd则监听该文件以获取用户进程的输出

rsyslogd守护进程在接收到用户进程或内核输入的日志后,会把它们输出道某些特定的日志文件。

  • 默认情况下,调试信息会保存在/var/log/debug
  • 普通信息保存至/var/log/messages
  • 内核消息保存至/var/log/kern.log

Linux系统日志体系:

7.1.2 syslog函数

应用程序使用syslog函数与rsyslogd守护进程通信

7.2 用户信息

7.2.1 UID、EUID、GID和EGID

大部分服务器必须要以root身份启动,但不能以root身份运行。

下面一组函数可以获取和设置当前进程的真实用户ID(UID)、有效用户ID(EUID)、真实组(GID)、有效组(EGID)

一个进程拥有两个用户ID:UID和EUID

  • EUID存在的目标:方便资源访问,使得运行程序的用户拥有该程序的有效用户权限

简单理解:比如su程序,su程序的有效用户权限是root,但是普通用户也可以在运行su程序时,拥有su程序的有效用户权限,也就是root(仅限于此程序)


小实验:测试进程的UID和EUID的区别

#include <unistd.h>
#include <stdio.h>

int main()
{
    uid_t uid = getuid();
    uid_t euid = geteuid();
    printf( "userid is %d, effective userid is: %d\n", uid, euid );
    return 0;
}

7.2.2 切换用户

以root身份启动的进程切换为以一个普通用户身份运行:

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 进程间关系

7.3.1 进程组

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

获取指定进程的PGID

设置PGID

每个进程组都有一个首领进程,其PGID和PID相同。

进程组将一直存在,直到其中所有进程都退出或者加入其他进程组

7.3.2 会话

一些有关联的进程组将形成一个会话(session)

创建一个会话:

此函数不能由进程组的首领进程调用,否则会产生一个错误

7.3.3 用ps命令查看进程关系

7.4 系统资源限制

Liux上运行的程序都会受到资源限制的影响,比如物理设备限制(CPU数量、内存数量等)、系统策略限制(CPU时间等),以及具体实现的限制(比如文件名的最大长度)。

7.5 改变工作目录和根目录

有些服务器程序还需要改变工作目录和根目录

一般来说,Web服务器的逻辑根目录并非文件系统的根目录“/”,而是站点的根目录(对于
Linux的Web服务来说,该目录一般是var/www/)

获取进程当前工作目录和改变进程工作目录的函数分别是:

7.6 服务器程序后台化

将服务器程序以守护进程的方式运行:

bool daemonize()
{
	// 创建子进程,关闭父进程,这样可以使得程序在后台运行
    pid_t pid = fork();
    if ( pid < 0 )
    {
        return false;
    }
    else if ( pid > 0 )
    {
        exit( 0 );
    }
	// 设置文件权限掩码
	// 当进程创建新文件 使用open等系统调用时,文件的权限将是 mode & 0777
    umask( 0 );
	
	// 创建新的会话,设置本进程为进程组的首领
    pid_t sid = setsid();
    if ( sid < 0 )
    {
        return false;
    }
	// 切换工作目录
    if ( ( chdir( "/" ) ) < 0 )
    {
        /* Log the failure */
        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;
}

结语

文章仅作为个人学习笔记记录,记录从0到1的一个过程

希望对您有一点点帮助,如有错误欢迎小伙伴指正

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。