Linux网络编程—Day10

news/2024/4/28 18:23:34/文章来源:https://blog.csdn.net/qq_43797135/article/details/130807412

Linux服务器程序规范

  • Linux服务器程序一般以后台进程形式运行。后台进程又称守护进程。它没有控制终端,因而也不会意外接收到用户输入。 守护进程的父进程通常是init进程(PID为1的进程);
  • Linux服务器程序通常有一套日志系统,它至少能输出日志到文件,有的高级服务器还能输出日志到专门的UDP服务器。大部分后台进程都在/var/log目录下拥有自己的日志目录;
  • Linux服务器程序一般以某个专门的非root身份运行。比如mysqld、httpd、syslogd等后台进程,分别拥有自己的运行账户mysql、apache和syslog;
  • Linux服务器程序通常是可配置的。服务器程序通常能处理很多命令行选项,如果一次运行的选项太多,则可以用配置文件来管理。绝大多数服务器程序都有配置文件,并存放在/etc目录下;
  • Linux服务器进程通常会在启动的时候生成一个PID文件并存入/var/run目录中,以记录该后台进程的PID;
  • Linux服务器程序通常需要考虑系统资源和限制,以预测自身能 承受多大负荷,比如进程可用文件描述符总数和内存总量等。

日志

服务器的调试和维护都需要一个专业的日志系统。Linux提供一个守护进程来处理系统日志——rsyslogd。rsyslogd守护进程既能接收用户进程输出的日志,又能接收内核日志。用户进程是通过调用syslog函数生成系统日志的。该函数将日志输出到一个UNIX本地域socket类型的文件/dev/log中, rsyslogd则监听该文件以获取用户进程的输出。rsyslogd守护进程在接收到用户进程或内核输入的日志后,会把它 们输出至某些特定的日志文件。默认情况下,调试信息会保存至var/log/debug文件,普通信息保存至/var/log/messages文件,内核消息则保存至/var/log/kern.log文件。

应用程序使用syslog函数与rsyslogd守护进程通信。syslog函数的定义如下:

#include<syslog.h>
void syslog(int priority,const char*message,...);

该函数采用可变参数来结构化输出,priority参数是所谓的设施值与日志级别的按位或,设施值的 默认值是LOG_USER,日志级别有如下几个:

#include<syslog.h>
#define LOG_EMERG 0/*系统不可用*/
#define LOG_ALERT 1/*报警,需要立即采取动作*/
#define LOG_CRIT 2/*非常严重的情况*/
#define LOG_ERR 3/*错误*/
#define LOG_WARNING 4/*警告*/
#define LOG_NOTICE 5/*通知*/
#define LOG_INFO 6/*信息*/
#define LOG_DEBUG 7/*调试*/

openlog可以改变syslog的默认输出方式:

#include<syslog.h>
void openlog(const char*ident,int logopt,int facility);

ident参数指定的字符串将被添加到日志消息的日期和时间之后,它通常被设置为程序的名字。logopt参数对后续syslog调用的行为进行配置。facility参数可用来修改syslog函数中的默认设施值。

日志的过滤也很重要。程序在开发阶段可能需要输出很多调试信息,而发布之后我们又需要将这些调试信息关闭。解决这个问题的方法并不是在程序发布之后删除调试代码(因为日后可能还需要用 到),而是简单地设置日志掩码,使日志级别大于日志掩码的日志信息被系统忽略。下面这个函数用于设置syslog的日志掩码:

#include<syslog.h>
int setlogmask(int maskpri);

maskpri参数指定日志掩码值。该函数始终会成功,它返回调用进程先前的日志掩码值。关闭日志功能:

#include<syslog.h>
void closelog();

用户信息

UID、EUID、GID和EGID

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

#include<sys/types.h>
#include<unistd.h>
uid_t getuid();/*获取真实用户ID*/
uid_t geteuid();/*获取有效用户ID*/
gid_t getgid();/*获取真实组ID*/
gid_t getegid();/*获取有效组ID*/
int setuid(uid_t uid);/*设置真实用户ID*/
int seteuid(uid_t uid);/*设置有效用户ID*/
int setgid(gid_t gid);/*设置真实组ID*/
int setegid(gid_t gid);/*设置有效组ID*/

切换用户

下面的代码清单展示了如何将以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;
}

进程间关系

进程组

Linux下每个进程都隶属于一个进程组,因此它们除了PID信息外,还有进程组ID(PGID)。我们可以用如下函数来获取指定进程的PGID:

#include<unistd.h>
pid_t getpgid(pid_t pid);

该函数成功时返回进程pid所属进程组的PGID,失败则返回-1并设置errno。每个进程组都有一个首领进程,其PGID和PID相同。进程组将一直存在,直到其中所有进程都退出,或者加入到其他进程组。设置PGID:

#include<unistd.h>
int setpgid(pid_t pid,pid_t pgid);

setpgid 函数成功时返回0,失败则返回-1并设置errno。一个进程只能设置自己或者其子进程的PGID。并且,当子进程调用exec系列函数后,我们也不能再在父进程中对它设置PGID。

会话

一些有关联的进程组将形成一个会话(session)。下面的函数用于创建一个会话:

#include<unistd.h>
pid_t setsid(void);

该函数不能由进程组的首领进程调用,否则将产生一个错误。对于非组首领的进程,调用该函数不仅创建新会话,而且有如下额外效果:

  • 调用进程成为会话的首领,此时该进程是新会话的唯一成员
  • 新建一个进程组,其PGID就是调用进程的PID,调用进程成为该组的首领。
  • 调用进程将甩开终端

该函数成功时返回新的进程组的PGID,失败则返回-1并设置errno。

用ps命令查看进程关系

执行ps命令可查看进程、进程组和会话之间的关系:

我们是在bash shell下执行ps和less命令的,所以ps和less命令的父进程是bash命令,这可以从PPID(父进程PID)一列看出。这3条命令创建 了1个会话(SID是2375)和2个进程组(PGID分别是2735和71265)。bash命令的PID、PGID和SID都相同,很明显它既是会话的首领,也是组2375的首领。ps命令则是组71256的首领,因为其PID也是71256;

 系统资源限制

 Linux上运行的程序都会受到资源限制的影响,比如物理设备限制 (CPU数量、内存数量等)、系统策略限制(CPU时间等),以及具体实现的限制(比如文件名的最大长度)。Linux系统资源限制可以通过如下一对函数来读取和设置:

#include<sys/resource.h>
int getrlimit(int resource,struct rlimit*rlim);
int setrlimit(int resource,const struct rlimit*rlim);

setrlimit和getrlimit成功时返回0,失败则返回-1并设置errno。rlim参数是rlimit结构体类型的指针,rlimit结构体的定义如下:

struct rlimit
{rlim_t rlim_cur;rlim_t rlim_max;
};

rlim_t是一个整数类型,它描述资源级别。rlim_cur成员指定资源的软限制,rlim_max成员指定资源的硬限制。软限制是一个建议性的、最好不要超越的限制,如果超越的话,系统可能向进程发送信号以终止其运行。例如,当进程CPU时间超过其软限制时,系统将向进程发送 SIGXCPU信号;当文件尺寸超过其软限制时,系统将向进程发送 SIGXFSZ信号。硬限制一般是软限制的上限。普通程序可以减小硬限制,而只有以root身份运行的程序才能增加硬限制。此外, 我们可以使用ulimit命令修改当前shell环境下的资源限制(软限制或/和硬限制),这种修改将对该shell启动的所有后续程序有效。我们也可以通过修改配置文件来改变系统软限制和硬限制,而且这种修改是永久。

resource参数指定资源限制类型。下列举了部分比较重要的资源限制类型:

 改变工作目录和根目录

有些服务器程序还需要改变工作目录和根目录,例如Web服务器,一般来说,Web服务器的逻辑根目录并非文件系统的根目录“/”,而是站点的根目录。

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

#include<unistd.h>
char*getcwd(char*buf,size_t size);
int chdir(const char*path);

buf参数指向的内存用于存储进程当前工作目录的绝对路径名,其大小由size参数指定。如果当前工作目录的绝对路径的长度超过了size,则getcwd将返回NULL,并设置errno为 ERANGE。如果buf为NULL并且size非0,则getcwd可能在内部使用 malloc动态分配内存,并将进程的当前工作目录存储在其中。如果是这种情况,则我们必须自己来释放getcwd在内部创建的这块内存。getcwd 函数成功时返回一个指向目标存储区的指针,失败则返回NULL并设置errno。

chdir函数的path参数指定要切换到的目标目录。它成功时返回0, 失败时返回-1并设置errno。

改变进程根目录的函数是chroot,其定义如下:

#include<unistd.h>
int chroot(const char*path);

path参数指定要切换到的目标根目录。它成功时返回0,失败时返 回-1并设置errno。chroot并不改变进程的当前工作目录,所以调用chroot之后,我们仍然需要使用chdir(“/”)来将工作目录切换至新的根目录。只有特权进程才能改变根目录。

服务器程序后台化

如何在代码中让一个进程以守护进程的方式运行? 守护进程的编写遵循一定的步骤,下面代码将服务器程序以守护进程的方式运行:

bool daemonize()
{pid_t pid = fork();if ( pid < 0 )return false;else if ( pid > 0 )exit( 0 );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 );open( "/dev/null", O_RDONLY );open( "/dev/null", O_RDWR );open( "/dev/null", O_RDWR );return true;
}

实际上,Linux提供了完成同样功能的库函数:

#include<unistd.h>
int daemon(int nochdir,int noclose);

其中,nochdir参数用于指定是否改变工作目录,如果给它传递0,则工作目录将被设置为“/”(根目录),否则继续使用当前工作目录。noclose参数为0时,标准输入、标准输出和标准错误输出都被重定向到/dev/null文件,否则依然使用原来的设备。该函数成功时返回0,失败则返回-1并设置errno。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_306511.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设备快线客户端软件V1.0用户手册

1.前言欢迎使用设备快线客户端软件产品。设备快线客户端软件简称DYClient,DYClient客户端是东用科技有限公司推出的一款用于远程维护的控制软件&#xff0c;主要为客户远程访问现场终端设备提供便捷的接入服务&#xff0c;并且通过DYClient客户端软件用户可以非常方便快捷的访问…

基于RetinaNet和TensorFlow Object Detection API实现目标检测(附源码)

文章目录 一、RetinaNet原理二、RetinaNet实现1. tf.train.CheckPoint简介2. RetinaNet的TensorFlow源码 一、RetinaNet原理 待补充 二、RetinaNet实现 1. tf.train.CheckPoint简介 待补充 2. RetinaNet的TensorFlow源码 Step 1&#xff1a;安装Tensorflow 2 Object Detect…

云原生之深入解析Docker容器退出码的含义和产生原因

一、前言 为什么我的容器没有运行?回答这个问题之前,需要知道 Docker 容器为什么退出?退出码会提示容器停止运行的情况?本文列出最常见的退出码,来回答两个重要问题:这些退出码是什么意思?导致该退出码的动作是什么?exit code:代表一个进程的返回码,通过系统调用 exi…

chatgpt赋能python:Python修改密码:一种安全可靠、快速高效的方式

Python 修改密码&#xff1a;一种安全可靠、快速高效的方式 在数字化时代&#xff0c;越来越多的信息被存储在计算机系统中&#xff0c;因此密码的保护变得尤为重要。人们需要保证他们的密码是安全可靠的&#xff0c;并定期更换密码。Python作为一种强大而且通用的编程语言&am…

iOS-最全的App上架教程

App上架教程 在上架App之前想要进行真机测试的同学&#xff0c;请查看《iOS- 最全的真机测试教程》&#xff0c;里面包含如何让多台电脑同时上架App和真机调试。 P12文件的使用详解 注意&#xff1a; 同样可以在Build Setting 的sign中设置证书&#xff0c;但是有点麻烦&…

生态伙伴 | 携手深圳科创学院,持续推动项目落地与成长

01 大赛介绍 中国硬件创新创客大赛始于2015年&#xff0c;由深圳华秋电子有限公司主办&#xff0c;至今已经成功举办八届&#xff0c;赛事范围覆盖华南、华东、华北三大地区&#xff0c;超10个省市区域。 大赛影响了超过45万工程师群体&#xff0c;吸引了35000多名硬创先锋报…

Linux文件系统、磁盘I/O是怎么工作的?

同CPU、内存一样&#xff0c;文件系统和磁盘I/O&#xff0c;也是Linux操作系统最核心的功能。磁盘为系统提供了最基本的持久化存储。文件系统则在磁盘基础上&#xff0c;提供了一个用来管理文件的树状结构。 目录&#xff1a; 一. 文件系统 1. 索引节点和目录项 2. 虚拟文件系…

抖音短视频APP的益与害都存在,今日详解其利弊

抖音是一款音乐创意短视频社交软件&#xff0c;是一个专注年轻人的15秒音乐短视频社区。这两年抖音太火了&#xff0c;不若与众身边的朋友百分之八十的朋友手机上都有这个软件&#xff0c;即使不拍也会抱着手机刷到停不下来。 首先&#xff0c;抖音其实给人们带来了许多乐趣和娱…

兼容性测试点和注意项,建议收藏

一&#xff1a;兼容性测试的概念&#xff1a;就是验证开发出来的程序在特定的运行环境中与特定的软件、硬件或数据相组合是否能正常运行、有无异常的测试过程。 二&#xff1a;兼容性测试的分类&#xff1a; &#xff08;1&#xff09;浏览器兼容性测试 指的是在浏览器上检查…

【CCF- CSP 202104-2 邻域均值 二维数组前缀和满分题解】

代码思路&#xff1a; 本题如果直接用暴力求解的话只能得70分。 运用到了二维数组的前缀和&#xff0c;难点是如何求出二维数组的前缀和并计算出领域所有元素的和。 注意计算平均数的时候要保证精度相同&#xff0c;所有都要化为double型&#xff0c;否则会出错。 首先&…

基于SpringBoot+Vue的闲一品交易平台设计与实现

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架下…

160743-62-4,DMG PEG2000,1,2-二肉豆蔻酰-rac-甘油-3-甲氧基聚乙二醇2000

DMG PEG2000&#xff0c;DMG-mPEG2000&#xff0c;1,2-二肉豆蔻酰-rac-甘油-3-甲氧基聚乙二醇2000 Product structure&#xff1a; Product specifications&#xff1a; 1.CAS No&#xff1a;160743-62-4 2.Molecular formula&#xff1a; C34H66O 3.Molecular weight&#xff…

基于openfaas托管脚本的实践

作者 | 张曦 一、openfaas产品背景 在云服务架构发展之初&#xff0c;这个方向上的思路是使开发者不需要关心搭建和管理后端应用程序。这里并没有提及无服务器这个概念&#xff0c;而是指后端基础设施由第三方来托管&#xff0c;需要的基础架构组建均以服务的形式提供&#x…

Paragon NTFS2023最新mac免费实用工具磁盘工具

mac虽然系统稳定&#xff0c;但在使用过程中也有一些瑕疵&#xff0c;如当mac连接到ntfs格式移动磁盘时&#xff0c;可能会出现移动磁盘无法在mac被正常读写的状况。遇到移动磁盘无法正常读写的状况&#xff0c;我们可以在mac中使用磁盘工具&#xff0c;以使mac获得对ntfs格式移…

100种思维模型之全局观思维模型-67

全局观思维模型&#xff0c;一个教我们由点到线&#xff0c;由线到面&#xff0c;再由面到体&#xff0c;不断的放大格局去思考问题的思维模型。 01、何谓全局观思维模型 一、全局观思维 什么叫全局观&#xff1f; 世界上的所有东西&#xff0c;都是被规律作用者的&#xff0c…

23种设计模式之命令模式(Command Pattern)

前言&#xff1a;大家好&#xff0c;我是小威&#xff0c;24届毕业生&#xff0c;在一家满意的公司实习。本篇文章将23种设计模式中的命令模式&#xff0c;此篇文章为一天学习一个设计模式系列文章&#xff0c;后面会分享其他模式知识。 如果文章有什么需要改进的地方还请大佬不…

【三】设计模式~~~创建型模式~~~抽象工厂模式(Java)

【学习难度&#xff1a;★★★★☆&#xff0c;使用频率&#xff1a;★★★★★】 3.1. 模式动机 在工厂方法模式中具体工厂负责生产具体的产品&#xff0c;每一个具体工厂对应一种具体产品&#xff0c;工厂方法也具有唯一性&#xff0c;一般情况下&#xff0c;一个具体工厂中…

OJ练习第116题——二进制矩阵中的最短路径(BFS)

二进制矩阵中的最短路径 力扣链接&#xff1a;1091. 二进制矩阵中的最短路径 题目描述 给你一个 n x n 的二进制矩阵 grid 中&#xff0c;返回矩阵中最短 畅通路径 的长度。如果不存在这样的路径&#xff0c;返回 -1 。 二进制矩阵中的 畅通路径 是一条从 左上角 单元格&am…

ORB-LSAM2:ComputeKeyPointsOctTree()提取特征:maxY = iniY + hCell + 6 为怎么是+6而不是+3?

如标题所示&#xff0c;本博客主要讲述 void ORBextractor::ComputeKeyPointsOctTree(vector<vector<KeyPoint>> &allKeypoints){}函数中maxY iniY hCell 6 为怎么是6而不是3&#xff1f; 为了连续性&#xff0c;会介绍一下ComputeKeyPointsOctTree函数&a…

PMP课堂模拟题目及解析(第13期)

121. 项目经理、团队成员以及若干干系人共同参与一次风险研讨会。已经根据风险管理计划生成并提供一份风险报告。若要为各个项目风险进行优先级排序&#xff0c;现在必须执行哪一项分析&#xff1f; A. 定量风险分析 B. 根本原因分析 C. 偏差分析 D. 定性风险分析 122. …