问题聚焦:
    除了网络通信外,服务器程序通常还必须考虑许多其他细节问题,这些细节问题涉及面逛且零碎,而且基本上是模板式的,所以称之为服务器程序规范。
    工欲善其事,必先利其器,这篇主要来探讨服务器程序的一些主要规范。

概览:
  • Linux服务器程序一般以后台程序的形式运行,后台进程又称为守护进程。
  • Linux服务器程序一般以某个专门的非root身份运行。
  • Linux服务器程序通常是可配置的,命令行或者配置文件的形式。
  • Linux服务器程序通常会在启动的时候生成一个PID文件,以记录该后台进程的PID。
  • Linux服务器程序通常需要考虑系统资源和限制。

日志
守护进程:rsyslogd
功能:接收用户进程输出的日志,又能接收内核日志。
用户日志函数:syslog
功能:生成系统日志,输出到一个UNIX本地域socket类型(AF_UNIX)的文件/dev/log中。rsyslogd则监听该文件以获取用户进程的输出。
内核日志函数:printk
功能:打印至内核的环状缓存中,环状缓存的内容直接映射到/proc/kmsg文件中。rsyslogd则通过读取该文件获得内核日志。
处理流程如下图所示:
syslog函数
功能:应用程序使用syslog函数与rsyslogd守护进程通信。
函数定义:
#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 7 /* 信息 */
#define LOG_DEBUG 8 /* 调试 */
函数:openlog
声明:
#include <syslog.h>
void openlog ( const char* ident, int logopt, int facility );
作用:改变syslog的默认输出方式,进一步结构化日志内容
函数说明:
ident:指定的字符串将被添加到日志消息的日期和时间之后,通常被设置为程序的名字。
logopt:对后续syslog调用的行为进行配置,可去下列值的按位或
#define    LOG_PID        0x01            /* 在日志消息中包含程序PID */
#define LOG_CONS 0x02 /* 如果消息不能记录到日志文件,则打印至终端 */
#define LOG_ODELAY 0x04 /* 延迟打开日志功能直到第一次调用syslog */
#define LOG_NDELAY 0x08 /* 不延迟打开日志功能 */
facility:修改syslog函数中的默认设施值
日志掩码:使日志级别大于日志掩码的日至信息被系统忽略。
函数:
#include <syslog.h>
int setlogmask( int maskpri );
函数说明:
maskpri:指定日志掩码值
该函数始终会成功,返回调用进程先前的日志掩码值。
关闭日志功能:
#include <syslog.h>
void closelog();

用户信息
用户信息包括:
  • UID:真是用户ID
  • EUID:有效用户ID
  • GID:真实组
  • EGID:有效组
#include <sys/types.h>
#include <unistd.h>
uid_t getuid();
uid_t geteuid();
gid_t getgid();
gid_t getegid();
int setuid( uid_t uid );
int seteuid( uid_t uid );
int setgid( gid_t gid );
int setegid( gid_t gid );
从函数名很容易看出函数的作用,就不解释了。
说明一下UID和EUID的区别:
一个进程拥有两个用户ID:UID和EUID。
EUID存在的目的是暂时提升当前用户的权限,方便资源访问,使得运行程序的用户拥有该资源的有效用户的权限,比如root用户。

进程间关系
进程组
进程中:每个进程都隶属于一个进程组,所以每个进程还有一个继承祖ID,PGID。
函数:
#include <unistd.h>
pid_t getpgid( pid_t pid );
每个进程都有一个首领进程,其PGID和PID相同。进程组将一直存在,直到其中所有进程都退出,或者加入到其他进程中。
设置PGID函数:
#include <unistd.h>
int setpgid( pid_t pid, pid_t pgid );
作用:将PID为pid的进程的PGID设置为pgid。
一个进程只能设置子集或者其子进程的PGID,并且,当子进程调用exec系列函数后,我们也不能再在父进程中对它设置。
会话
会话:一些有关联的进程组形成一个会话。
函数:
#include <unistd.h>
pid_t setsid( void );
函数说明:
  1. 该函数不能由进程组的首领进程调用,否则将产生一个错误。只能由非组首领的进程调用。
  2. 调用后创建新会话
  3. 调用几次呢很难过成为会话的首领,此时该进程是该会话的唯一成员
  4. 调用一个进程组,其PGID就是调用进程的PID,调用进程成为该组的首领。
  5. 调用进程将甩开终端
  6. 调用成功返回新的进程组的PGID,失败则返回-1并设置errno
会话ID即为首领所在进程组的PGID,获取函数
#include <unistd.h>
pid_t getsid ( pid_t pid );
用ps命令查看进程关系
调用结果如图(PPID为父进程的PID):
 
三个进程的关系如图:
 

系统资源限制
Linux系统资源限制可以通过如下一对函数来读取和设置:
#include <sys/resource.h>
int getrlimit( int resource, struct rlimit *rlim );
int setrlimit( int resource, const struct rlimit *rlim );
rlimit结构体的定义如下:
struct rlimit
{
rlim_t rlim_cur;
rlim_t rlim_max;
};
函数说明:
rlim_t是一个整数类型,它描述资源级别。
rlim_cur成员指定资源的软限制,建议性。
rlim_max成员指定资源的硬限制。
resource:指定资源限制类型。
部分资源限制类型如下所示:
 
 

改变工作目录和根目录
获取当前工作目录和改变进程工作目录的函数分别是:
#include <unistd.h>
char* getcwd( char* buf, size_t size );
int chdir( const char* path );
函数说明:
buf:指向的内存用于存储进程当前工作目录的绝对路径
size:指定buf的大小,如果当前工作目录的绝对路径的长度超过了size,则getcwd将返回NULL,并设置errno为ERANGE。
path:指定要切换的目标目录。成功时返回0,失败返回-1并设置errno。
改变进程根目录的函数是chroot,其定义如下:
#include <unistd.h>
int chroot( const char* path );
函数说明:
path:指定要切换的目标根目录。
chroot并不改变进程的当前工作目录,所以调用chroot之后,我们仍需要使用chdir("/")来将工作目录切换至新的根目录。

服务器程序后台化
Key word:守护进程
后面将以专题的形式总结。
小结:
这章虽然叫做程序规范,其实更多的是介绍一些开发过程,特别是中大型项目中很有用的技巧,可以提高我们的开发和调试效率。
后面将会介绍一些常用的设计框架,这些都是比较基础的知识。后面如果还有时间,希望可以用我们学到的这些知识做一个小项目出来。也算是学以致用了。
参考资料:
《Linux高性能服务器编程》

服务器编程入门(5)Linux服务器程序规范的更多相关文章

  1. 服务器编程入门(4)Linux网络编程基础API

      问题聚焦:     这节介绍的不仅是网络编程的几个API     更重要的是,探讨了Linux网络编程基础API与内核中TCP/IP协议族之间的关系.     这节主要介绍三个方面的内容:套接字( ...

  2. 服务器编程入门(10)TCP回射服务器实现 - 并发

    问题聚焦:     在前面我们大概浏览了一下服务器编程需要掌握的一些知识和技术,以及架构思想.        实践,才是检验真理的唯一标准..从这节起我们将在这些技术的基础上,一步步实现以及完善一个服 ...

  3. 服务器编程入门(7)I/O复用

    问题聚焦:     前篇提到了I/O处理单元的四种I/O模型.     本篇详细介绍实现这些I/O模型所用到的相关技术.     核心思想:I/O复用 使用情景: 客户端程序要同时处理多个socket ...

  4. 服务器编程入门(3)TCP协议详解

    问题聚焦:     本节从如下四个方面讨论TCP协议:     TCP头部信息:指定通信的源端端口号.目的端端口号.管理TCP连接,控制两个方向的数据流     TCP状态转移过程:TCP连接的任意一 ...

  5. 服务器编程入门(2)IP协议详解

    问题聚焦:     IP协议是TCP/IP协议族的核心协议,也是socket网络编程的基础之一.这里从两个方面较为深入地探讨IP协议:     1,IP头部信息(指定IP通信的源端IP地址,目的端IP ...

  6. 服务器编程入门(1)TCP/IP协议族

    问题聚焦: 简单地梳理一下TCP/IP各层的功能和常用协议 详细了解ARP(数据链路层)和DNS(应用层)协议的工作原理 1 TCP/IP协议族体系结构 数据链路层:     职责:实现网卡接口的网络 ...

  7. 服务器编程入门(11)TCP并发回射服务器实现 - 单线程select实现

    问题聚焦: 当客户端阻塞于从标准输入接收数据时,将读取不到别的途径发过来的必要信息,如TCP发过来的FIN标志. 因此,进程需要内核一旦发现进程指定的一个或多个IO条件就绪(即输入已准备好被读取,或者 ...

  8. 从Windows 服务器通过sync向Linux服务器定时同步文件

    本文解决的是Windows 下目录及文件向Linux同步的问题,Windows向 Windows同步的请参考:http://www.idcfree.com/article-852-1.html 环境介 ...

  9. 服务器编程入门(13) Linux套接字设置超时的三种方法

    摘要:     本文介绍在套接字的I/O操作上设置超时的三种方法. 图片可能有点宽,看不到的童鞋可以点击图片查看完整图片.. 1 调用alarm 使用SIGALRM为connect设置超时 设置方法: ...

随机推荐

  1. 1.1.4-学习Opencv与MFC混合编程之---画图工具 画椭圆

    源代码地址:http://download.csdn.net/detail/nuptboyzhb/3961690 1.    增加‘椭圆’菜单项,设置属性,添加类向导: 2.    编辑消息处理函数, ...

  2. jssdk微信图片上传功能

    /*wx.config({ debug: false, appId: data.appid, timestamp: data.timestamp, nonceStr: data.nonceStr, s ...

  3. poj 2777 Count Color(线段树区区+染色问题)

    题目链接:  poj 2777 Count Color 题目大意:  给出一块长度为n的板,区间范围[1,n],和m种染料 k次操作,C  a  b  c 把区间[a,b]涂为c色,P  a  b 查 ...

  4. Linux - Linux系统目录架构

    Linux系统目录架构   Bin: 保存的是二进制可执行文件,也就是我们所敲的那些命令. Boot: 引导目录,整个操作系统的引导启动都是在boot目录下面.最主要的文件是vmLinuz-……,内核 ...

  5. 让进程在后台可靠运行的几种方法 nohup,setsid,&,disown,CTRL-z ,screen

    让进程在后台可靠运行的几种方法 几年前在developerWorks上面看到的文章,感觉非常实用,又简单整理了一下,转到这里,希望给看到的人带来一些帮助.文中提到的nohup和subshell方式一直 ...

  6. Fedora Linux 下安装配置C开发环境Code::Blocks

    一.提前的话要说C语言和Linux的关系大家应该都不会陌生,Linux系统内核就是用C语言开发的,所以所有的Linux系统下面 都会有C的编译调试工具,不过这些工具都是命令式的,正式开发的话会很不方便 ...

  7. android端从服务器抓取的几种常见的数据的处理方式

    1.图片 public void look(View v) { String path = et_path.getText().toString(); try { URL url = new URL( ...

  8. Swift - 类型判断is 与 类型转换as

    在Swift中,通常使用is和as操作符来实现类型检查和转换.下面通过样例来演示使用方法,首先定义几个类. 1 2 3 4 5 6 7 8 9 10 11 //基类,人类 class Human{ } ...

  9. Swift - 计算次方(2的N次方,2的随机次方)

    1,使用<<计算2的N次方 1 2 var value = 1<<4  //2的4次方 var value = 1<<Int(arc4random_uniform( ...

  10. Visual Studio Code中文文档

    Visual Studio Code中文文档 Visual Studio Code是一个轻量级但是十分强大的源代码编辑器,重要的是它在Windows, OS X 和Linux操作系统的桌面上均可运行. ...