Linux 服务器编程学习笔记⑤
# Linux 服务器程序规范
# 服务器程序规范
Linux 服务器程序一般以后台进程形式运行。后台进程又称守护进程,其父进程通常是 init 进程(PID 为 1)。
Linux 服务器程序通常有一套日志系统。
Linux 服务器程序一般以某个专门的非 root 身份运行。
Linux 服务器程序通常能配置命令行参数。
Linux 服务器程序通常启动时会生成一个 PID 文件存入 /var/run 目录中,以记录该后台进程 PID。
Linux 服务器程序通常需要考虑系统资源和限制。
# 日志
Linux 提供一个守护进程(syslogd)来处理系统日志,现在使用其的升级版(rsyslogd)。其既接收用户进程输出的日志,也接收内核日志。用户进程调用 syslog 函数生成系统日志(先传输到 /dev/log 再被 rsyslogd 监听)。内核由 printk 函数打印至内核环状缓存中,其被直接映射到 /proc/kmsg 文件中再被 rsyslogd 读取。如下图:
注:默认情况,调试信息保存在 /var/log/debug,普通信息保存在 /var/log/messages,内核消息保存在 /var/log/kern.log。
syslog 函数
#include <syslog.h>
void syslog(int priority, const char* message, ...)
priority 参数是设施值和日志级别按位或。日志级别如下:
![](https://blog-web-image.oss-cn-shanghai.aliyuncs.com/computer/linux/5/2 .png)
openlog 函数
openlog 函数可以改变 syslog 的默认输出方式。
#include <syslog.h>
void openlog(const char* ident, int logopt, int facility)
ident 参数指定的字符串将被添加到日志消息的日期和时间之后(通常被设置为程序的名字),logopt 参数配置 syslog 行为(如 LOG_PID 表示日志消息中包含程序 PID)。facility 修改 syslog 函数中的默认设施值。
日志掩码
#include <syslog.h>
int setlogmask(int maskpri);
void closelog();
日志级别大于日志掩码的日志信息将会被忽略(开发阶段需要的一些日志在发布之后可能不再需要)。
# 进程组 & 会话
Linux 下每个进程都隶属于一个进程组(PGID),进程组的首领其 PID 与 PGID 相同。一个进程组往往是一组协作完成一项共同最终任务的进程。 一组关联的进程组可以形成一个会话。
# 资源限制
Linux 上运行的程序都会受到资源限制的影响。限制分为软限制和硬限制,超越软限制时,系统可能向进程发送信号以终止其运行,且软限制小于硬限制。硬限制只可以被 root 身份执行的程序增加。
下面的函数可以读取设置资源限制:
#include <sys/resource.h>
int getrlimit(int resource, struct rlimit* rlim);
int setrlimit(int resource, const struct rlimit* rlim);
struct rlimit
{
rlim_t rlim_cur;//软限制
rlim_t rlim_max;//硬限制
}
resource 代表资源类型(如 RLIMIT_AS 进程虚拟内存总限制; RLIMIT_CPU 进程 CPU 时间限制)。
两个函数成功时都返回 0,失败返回 - 1 并设置 errno。
# 改变工作目录和根目录
一些服务器程序需要改变工作目录和根目录(例如 web 服务器逻辑根目录并非文件系统的根目录)。
获取和改变进程工作目录的函数:
#include <unistd.h>
char* getcwd(char* buf, size_t size);
int chdir(const char* path);
buf 存储进程当前工作目录绝对路径名;path 是要切换的目标目录。成功都返回 0 ,失败返回 -1 并设置 errno。
改变进程根目录的函数:
#include <unistd.h>
int chroot(const char* path);
参数与返回值同上,注:只有特权进程才能改变根目录。
# 服务器程序后台化
可以通过产生子进程在杀死父进程的方式使程序后台化,但是 Linux 提供了后台化的库函数:
#include <unistd.h>
int daemon(int nochdir, int noclose);
nochdir 指示是否改变工作目录,如果输入 0 则工作目录为 “/”(根目录),否则继续为原来的目录。noclose 为 0 时,标准输入、输出、标准错误输出都被重定向到 /dev/null,否则将使用原来的设备。
成功时返回 0,失败返回 - 1,并设置errno。