Linux服务器程序规范

2023-10-26

Linux服务器程序规范

  • Linux服务器程序一般都是以后台进程形式运行,后台进程又称为守护进程(daemon),其没有控制终端,不会意外接收到用户输入。守护进程的父进程通常是init进程(PID为1的进程);
  • Linux服务器程序通常有一套日志系统,其至少能输出日志到文件,有的高级服务器还能输出日志到专门的UDP服务器;
  • Linux服务器程序一般以某个专门的非root身份运行;
  • Linux服务器程序通常是可配置的;
  • Linux服务器进程通常会在启动的时候生成一个PID文件并存入/var/run记录中,以记录后台进程的PID;
  • Linux服务器程序通常需要考虑系统资源和限制,以预测自身能承受多大负荷,比如进程可用文件描述符总数和内存总量等;

用户信息

在Unix进程中涉及多个用户ID和用户组ID,包括如下:

  • 实际用户ID和实际用户组ID: 标识我是谁。也就是登录用户的uid和gid,比如我的Linux以simon登录,在Linux运行的所有的命令的实际用户ID都是simon的uid,实际用户组ID都是simon的gid(可以用id命令查看)。
  • 有效用户ID和有效用户组ID:进程用来决定我们对资源的访问限制,一般情况下,有效用户ID等于实际用户ID,有效用户组ID等于实际用户组ID。当设置用户ID(SUID)位设置,则有效用户ID等于文件所有者的uid,而不是实际用户ID;同样,如果设置了设置-用户组-ID(SGID),则有效用户ID等于文件所有者的gid,而不是实际用户组ID;

有效用户ID为root的进程称为特权进程;

会话

一些有关联的进程组可以形成一个会话,下面函数用于创建一个会话:

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

该函数不能由进程组的首领进程调用,否则产生错误。对于非首领进程,调用该函数不仅创建新会话,还有如下作用:

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

服务器程序后台化

后台化的步骤:

  • 创建子进程,父进程退出;
  • 在子进程中创建新会话(setsid());
  • 改变当前目录为根目录,防止占用可卸载的文件系统;
  • 重设文件权限掩码,防止继承的文件创建屏蔽字拒绝某些权限;
  • 关闭文件描述符,继承的打开文件不会用到;
  • 开始执行守护进程核心工作;
  • 守护进程退出处理;
bool daemonize(){]
    pid_t pid = fork();
    if(pid < 0){
        return false;
    }
    else if(pid > 0){
        exit(0);
    }
    //设置文件权限掩码,当进程创建新文件时,文件的权限将是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;
}

守护进程详细说明

事件处理模式

Reactor模式

Reactor:要求主线程只负责监听文件描述符上是否有事件发生,有的话就立即将该事件通知工作线程,除此之外,主线程不做任何其他实质性工作,读写数据,接收新的连接,以及处理客户请求均在工作线程完成。

这里写图片描述

Proactor模式

与Reactor模式不同,Proactor模式将所有I/O操作都交给主线程和内核来处理,工作线程仅仅负责业务逻辑,因此,Proactor模式更符合服务器编程框架。

使用异步I/O模型(以aio_read和aio_write)实现Proactor模式的工作流程:

1) 主线程调用aio_read函数向内核注册socket上的读完成事件,并告诉内核用户读缓冲区的位置,以及读操作完成时如何通知应用程序(以信号为例);
2) 主线程继续处理其他逻辑;
3) 当socket上的数据被读入用户缓冲区,内核将向应用程序发送一个信号,以通知应用程序数据可用;
4)应用程序预定义好的信号处理函数选择一个工作线程来处理客户请求,工作线程处理完客户请求之后,调用aio_write函数向内核注册socket上的写完成事件,并告诉内核用户缓冲区的位置,以及写操作完成时如何通知应用程序(以信号为例);
5)主线程继续处理其他逻辑;
6)当用户缓冲区的数据被写入socket之后,内核将向应用程序发送一个信号,以通知应用程序数据已经发送完毕;
7)应用程序预定义好的信号处理函数选择一个工作线程来做善后处理,比如决定是否关闭socket;

这里写图片描述

模拟Proactor模式

使用同步I/O模拟Proactor模式的一种方法,原理:主线程执行数据读写操作,读写完成之后,主线程向工作线程通知这一“完成事件”,那么从工作线程角度来看,其直接获得了数据读写的结果,接下来要做的只是对读写的结果进行逻辑处理;

工作流程:

1) 主线程往epoll内核时间表注册socket上的读就绪事件;
2) 主线程调用epoll_wait等待socket上有数据可读;
3) 当socket上有数据可读,epoll_wait通知主线程,主线程从从socket循环读取数据,知道没有更多数据可读,然后将读取到的数据封装成一个请求对象插入请求队列;
4) 睡眠在请求队列上的某个工作线程被唤醒,它获得请求对象并处理客户请求,然后往epoll内核事件表注册socket上的写就绪事件;
5) 主线程调用epoll_wait等待socket可写;
6) 当socket可写时,epoll_wait通知主线程,主线程往socket上写入服务器处理客户请求的结果;

流程图:

这里写图片描述

高效并发模式

并发编程的目的是让程序“同时”执行多个任务:
如果是计算密集型的,并发编程没有优势,反而由任务的切换导致效率降低;
如果程序是I/O密集型的,比如经常读写文件,访问数据库等,则情况就不同了,由于I/O操作的速度远没有CPU计算的速度快,所以让程序阻塞于I/O操作将浪费大量的CPU时间,如果程序有多个执行进程,则当前被I/O操作所阻塞的执行线程可主动放弃CPU(或由OS调度),并将执行权转移到其他线程,这样一来,CPU就可以用来做更加有意义的事情(除非所有线程都同时被I/O操作所阻塞),而不是等待I/O操作完成,因此CPU的利用率显著提升;

半同步半异步模式

半同步半异步模式中的同步和异步与I/O模式中的同步和异步是完全不同的概念。

  • I/O模型中,同步和异步区分的是内核向应用程序通知的何种I/O事件(是就绪事件还是完成事件),以及该由谁来完成I/O操作(是应用程序还是内核);
  • 并发模式中,同步指程序完全按照代码序列的顺序执行,异步值程序的执行需要系统事件来驱动;

在半同步半异步模式中,同步线程用于处理客户逻辑,异步线程用于处理I/O事件,异步线程监听到客户请求后,就将其封装成请求对象并插入请求队列中,请求队列将通知某个工作在同步模式的工作线程读取并处理该请求对象,具体选择哪个工作线程来为新的客户请求服务,取决于请求队列的设计;

半同步半反应堆模式:使用模拟的Proactor时间处理模式,主线程完成数据的读写,主线程一般会将应用程序数据、任务类型等信息封装成一个任务对象,将其(或指向任务队列的指针)插入请求队列,工作线程从请求队列中取得任务对象之后,即可直接处理之,无需读写操作了。

但有如下缺点:

  • 主线程和工作线程共享请求队列,主线程往请求队列中添加任务,或者工作线程从请求队列中取出任务,都需要对请求队列加锁保护,白白消耗CPU时间;
  • 每个工作线程在同一时间只能处理一个客户请求,如果客户请求数量较多,而工作线程较少,则请求队列中将堆积很多任务对象,客户端的响应速度将越来越慢,如果通过增加工作线程来解决这个问题,则工作线程的切换也将耗费大量CPU时间;

提高服务器性能的建议

影响服务器性能的首要因素是系统的硬件资源,比如CPU的个数、速度、内存的大小等;
从“软环境”提升服务器的性能,“软环境”:

  • 系统的软件资源:操作系统允许用户打开的最大文件描述符的数量;
  • 服务器程序本身:如何从编程的角度确保服务器的性能?
    • 池、数据复制、上下文切换、锁

“浪费”服务器的硬件资源,以换取其运行效率,这就是池的概念。

池是一组资源的集合,这组资源在服务器启动之初就被完全创建好并初始化,称为静态资源分配;

当服务器进入正式运行阶段,即开始处理客户请求的时候,如果它需要相关的资源,可直接从池中获取,无须动态分配。直接从池中获取所需资源比动态分配资源的速度快的多,因为分配系统资源的系统调用时很耗时的。当服务器处理完一个客户连接之后,可以把相关的连接放入池中,无须执行系统调用释放资源。

池相当于服务器管理系统资源的应用层设施,避免了服务器对内核的频繁访问;

  • 内存池:通常用于socket的接收和发送缓存;
  • 进程池和线程池:可直接从其中获得一个执行实体,无须动态调用fork或pthread_create等函数创建进程和线程;
  • 连接池:服务器或服务器机群内部的永久链接;
数据复制

高性能服务器应该避免不必要的数据复制,尤其是当数据复制发生在用户代码和内核之间的时候。可以使用“零拷贝”函数进行数据的复制,如sendfile等;

用户代码内部(不访问内核)的数据复制也应该避免,可以使用共享内存共享数据而不是使用管道或消息队列传递数据;

上下文切换和锁

并发程序必须考虑上下文切换的问题,即进程切换或线程切换导致的系统开销。即使是I/O密集型的服务器,也不应该使用过多的工作线程(或工作进程),否则线程间的切换将占用大量的CPU时间,服务器真正用处理业务逻辑的CPU时间的比重就显得不足了。

多线程服务器的一个优点:不同线程可以同时运行在不同的CPU上,当线程的数量不大于CPU的数目时,上下文切换就不是问题了。

并发程序需要考虑的另外一个问题是共享资源的加锁保护,锁通常被认为是导致服务器效率低下的一个因素,因为由它引入的代码不仅不处理任何业务逻辑,而且需要访问内核资源。因此,服务器如果有更好的解决方案,应该避免使用锁。当服务器必须使用锁,则可以考虑减小锁的粒度;

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux服务器程序规范 的相关文章

  • 《UVM实战》学习笔记——第六章 sequence机制

    文章目录 前言 一 sequence的启动与执行 1 启动 2 启动方式 3 sequence分类 二 sequence的仲裁机制 1 sequence相关的宏 2 sequencer的仲裁算法 6种 3 sequence独占sequenc
  • USB HUB简述

    概述 hub 集线器 连接在host与device之间的一种用于usb接口扩展的usb设备 可以将一个usb上行接口扩展为多个下行接口 使得一个host可以同时与多个device连接 一般来说 一块hub桥接芯片可扩展4个usb接口 而市面
  • ‘dtools’不是内部或外部命令,也不是可运行的程序或批处理文件,个人解决方案

    powershell或cmd执行时出现 dtools 不是内部或外部命令 也不是可运行的程序或批处理文件 奇怪的是 我的工程目录下明明有dtools exe可执行文件 搜索引擎上多数反馈是添加C system32等路径到环境变量 但后续发现
  • 亲密关系-【沟通提示】-如何把学习到的东西用到生活中

    关于亲密关系 我学到了这么多 可为什么ta对这些毫不在意 我知道课里的观点都很重要 可我该怎么教会ta ta没有意识 看画面 案例 妈妈说话总是带有攻击性 总是骂她 怎么说 常见误区 你不要老师贬低我 对方苦苦思考 我到底该怎么办 你下意识
  • java中的多重循环

    多重循环 一个循环体内又包含另一个完整的循环结构 如下 while 循环条件1 循环操作1 while 循环条件2 循环操作2 do 循环操作1 do 循环操作2 while 循环条件2 while 循环条件1 for 循环条件1 循环操作
  • Docker - 使用Docker Compose部署应用

    简介 Docker Compose是一个基于Docker Engine进行安装的Python工具 该工具使得用户可以在一个声明式的配置文件中定义一个多容器的应用 在Docker节点上 以单引擎模式 Single Engine Mode 进行
  • 手写算法-python代码实现Lasso回归

    手写算法 python代码实现Lasso回归 Lasso回归简介 Lasso回归分析与python代码实现 1 python实现坐标轴下降法求解Lasso 调用sklearn的Lasso回归对比 2 近似梯度下降法python代码实现Las
  • 【直达本质讲运放】运放的“第一原理”式定量分析法

    数电 模电那两本书我也完整地翻过一 二遍 诶我为什么用 也 下面就是来点不复杂的 如果是那还不如直接把书的内容粘过来呢 对于运放的定量分析 虚短虚断 就如同 奇变偶不变 一样喜闻乐见的普及 但是对于什么时候用 虚短 什么时候用 虚断 学习的
  • Ridge和Lasso回归

    上周看了看回归方面的知识 顺便复 xue 习一下Ridge 岭回归 和Lasso回归 套索回归 瞅到了一篇英文博客讲得不错 翻译一下 本文翻译自 Ridge and Lasso Regression 本文是一篇Josh Starmer关于
  • 常用网络协议神图

  • 凸优化(一)——Introduction

    Introduction 一 最优化问题的数学表达 在最优问题中 其数学表达往往能化成标准形式 如下 minimizef0 x subject tofi x bi i 1 m begin aligned minimize quad f 0
  • 微信小程序对上传的图片进行裁剪

    背景 使用uniapp中uni chooseImage的裁剪参数crop只能在App中生效 在微信小程序中不生效 实现思路 uni chooseImage打开相册获取图片路径 uni chooseImage OBJECT uni app官网

随机推荐

  • c++面试记录

    1 数组与指针区别 数组 数组是用于储存多个相同类型数据的集合 指针 指针是一个变量 但是它和普通变量不一样 它存放的是其它变量在内存中的地址 赋值 数组 只能一个一个元素的赋值或拷贝 指针 指针变量可以相互赋值 表示范围 数组有效范围就是
  • flink table 使用Kafka Connector处理嵌套json

    使用flink table api 连接kafka 处理json类型数据 单层json处理比较简单 官方或网上都有很多例子 处理嵌套的json数据没什么介绍 处理嵌套json数据主要是schema定义 StreamExecutionEnvi
  • Linux系统之使用yum安装Redis数据库

    Linux系统之使用yum安装Redis数据库 一 redis介绍 1 redis解释 2 redis特点 3 redis使用场景 二 检查系统版本 1 检查系统版本 2 检查内核版本 三 检查yum仓库状态 四 查看系统默认提供的redi
  • mysql数据恢复,使用binlog配置恢复未备份数据

    使用mysqlbinlog配置 恢复数据库 什么是mysqlbinlog binlog是记录所有数据库表结构变更 例如CREATE ALTER TABLE 以及表数据修改 INSERT UPDATE DELETE 的二进制日志 binlog
  • 命令行参数设计

    1 目的 众多通用的小功能 制作为一个小工具 然后通过命令行来进行交互 使用非常的简便 本规范是为了统一命令行参数的设计 使得大家在制作或使用命令行工具时 能够更加有共享 进行会更加方便 2 适用范围 所有命令行工具参数的设计 3 基本原则
  • #SATA# SATA 实际管脚接线图

    前言 概述 实际接线管脚图 PATA 接口 M 2 U 2 AHCI NVMe 概述 SATA是Serial ATA的缩写 即串行ATA 它是一种电脑总线 主要功能是用作主板和大量存储设备 如硬盘及光盘驱动器 之间的数据传输 这是一种完全不
  • 迁移学习:他山之石,可以攻玉【VALSE Webinar】Panel实录

    编者按 迁移学习是机器学习与计算机视觉中的重要研究问题之一 旨在研究如何将一个领域的知识迁移到另外的领域 具有重要的研究意义与应用价值 但迁移学习又会存在哪些局限性 在实际应用中的价值是什么 未来的发展方向在哪里 为此 VALSE Webi
  • docker 数据持久化

    文章目录 定制镜像持久化 需求 实现 数据卷持久化 数据卷简介 数据卷的特性 创建读写数据卷 停止容器后的操作 查看数据卷详情 创建只写数据卷 查看数据卷详情 创建共享数据卷 Dockerfile持久化 创建Dockerfile 构建和运行
  • 大二上学期数据结构课程设计

    1 报数问题 问题描述 有n个小朋友围成一圈玩游戏 小朋友从1至n编号 2号小朋友坐在1号小朋友的顺时针方向 3号小朋友坐在2号小朋友的顺时针方向 1号小朋友坐在n号小朋友的顺时针方向 游戏开始 从1号小朋友开始顺时针报数 接下来每个小朋友
  • 安装TensorFlow遇到no module named ‘tensorflow’问题解决方法

    按照这个博客https blog csdn net qq 16633405 article details 79941696里的步骤安装TensorFlow时遇到no module named tensorflow 虽然作者给出了一个解决方
  • 文本多分类之Doc2Vec实战篇

    本文链接 https blog csdn net weixin 42608414 article details 88391760 版权 在我之前的几篇博客中 我介绍了两种文档向量化的表示方法 如Sklearn的CountVectorize
  • 1.3. 分治法—最近点对问题

    1 问题描述 给定平面S上n个点 找其中的一对点 使得在n个点组成的所有点对中 该点对间的距离最小 2 求解过程 划分 将集合S分成两个大小基本相等的子集 S 1 S 1 S1 和 S
  • linux 基础知识考试试题,Linux常识型试题

    Linux常识型试题 发布时间 2011 06 06 18 11 10来源 红联作者 lijiang i s 本帖最后由 lijiang 于 2011 10 22 17 51 编辑 i 一 填空题 1 链接分为 和 2 安装Linux系统对
  • 解决Linux界面显示问号字符?与Failed to set locale, defaulting to C报错

    解决方法 暂时性处理 export LC ALL zh CN UTF 8 一劳永逸 vim etc bashrc 然后在最后一行写入 export LC ALL zh CN UTF 8 问题复现 解析 当输入 locale 会得到如下结果
  • 数据结构----利用栈实现表达式的计算

    利用栈实现表达式的计算 例如 12 5 6 9 7 8 5 6 8 5 6 12 要解决的问题主要有两个 和 的运算顺序的处理问题 括号内的表达式优先运算问题 这里利用栈来解决这两个问题 首先我们设置两个栈 一个符号栈 一个数字栈 下面我们
  • Novell数据备份

    从昨天下午到现在 才搞定 关总不提示的情况下 我一直认为xvRf是更新备份数据 cvRf是全部备份 其实则不然 关总告诉我 xvRf是导入数据 而cvRf才是备份数据 如果网络成功链接的话 那NDS服务器的数据就会被老数据覆盖了 幸好幸好
  • Android Studio day_01 初识线性布局和相对布局还有按钮

    序章 今天学习了线性布局 LinearLayout 和相对布局 RelativeLayout 还有Button按钮 布局是要用和进行结束的 至于Botton按钮嘛 使用 gt 结束就好啦 相对布局 RelativeLayout 相对布局我理
  • 卸载npm和安装npm_使用`npm uninstall`卸载npm软件包

    卸载npm和安装npm To uninstall a package you have previously installed locally using npm install
  • 激光雷达对植被冠层结构和SIF同时探测展望

    前言 陆表植被在全球碳循环中起着不可替代的作用 但现阶段 人们对气候变化与植被生态理化功能的关系的研究还不够完善 为了提高气候预测以及缓解气候恶化的速率 对植被参数比如 叶面积指数 leaf 植被冠层结构 canopy 和生态系统以及区域尺
  • Linux服务器程序规范

    Linux服务器程序规范 Linux服务器程序一般都是以后台进程形式运行 后台进程又称为守护进程 daemon 其没有控制终端 不会意外接收到用户输入 守护进程的父进程通常是init进程 PID为1的进程 Linux服务器程序通常有一套日志