总结《Linux高性能服务器编程》第七章
第7章 Linux服务器程序规范
日志
-
Linux系统日志
-
Linux系统使用**rsyslogd后台进程(daemon)**来处理系统日志;
-
用户进程通过调用syslog函数生成系统日志,并输出到AF_UNIX类型的文件/dev/log中,rsyslogd 则监听该文件以获取用户进程的输出;
-
rsyslogd后台进程在接收到用户进程或内核输入的日志后,会把它们输出至某些特定的日志文件:
- 调试信息:/var/log/debug;
- 普通信息:/var/log/messages;
- 内核消息:/var/log/kern.log;
-
rsyslogd的主配置文件是/etc/rsyslog.conf,可以设置内核日志输入路径,是否接收UDP/TCP日志及其监听端口,权限等等;
-
-
syslog函数
-
应用程序使用syslog函数与rsyslogd后台进程通信
#include<syslog.h> void syslog(int priority,const char*message,...);
-
openlog函数可以改变syslog的默认输出方式;
-
setlogmask函数用于设置syslog的日志掩码,实现日志的过滤,使日志级别大于日志掩码的日志信息被系统忽略;
-
closelog函数关闭日志功能;
-
用户信息
-
UID、EUID、GID和EGID
-
大部分服务器必须以root身份启动,但不能以root身份运行;
-
一个进程拥有两个用户ID:UID和EUID
- EUID存在的目的是方便资源访问,使得运行程序的用户拥有该程序的有效用户的权限;
- 如:su程序的有效用户就是该程序的所有者root;
-
下面这一组函数可以获取和设置当前进程的真实用户ID(UID)、有效用户ID(EUID)、真实组ID(GID)和有效组ID(EGID)
#include<sys/types.h> #include<unistd.h> uid_t getuid();/*获取真实用户ID*/ int setuid(uid_t uid);/*设置真实用户ID*/ //euid、gid、egid同理
-
-
切换用户
进程间关系
-
进程组
-
Linux下每个进程都隶属于一个进程组,因此它们有进程组ID(PGID),可以用如下函数来获取及设置指定进程的PGID
#include<unistd.h> pid_t getpgid(pid_t pid); int setpgid(pid_t pid,pid_t pgid);
-
一个进程只能设置自己或者其子进程的PGID,并且,当子进程调用exec系列函数后,也不能再在父进程中对它设置PGID;
-
每个进程组都有一个首领进程,其PGID和PID相同;
-
-
会话
-
一些有关联的进程组将形成一个会话(session),下面的函数用于创建一个会话
#include<unistd.h> pid_t setsid(void);
-
该函数不能由进程组的首领进程调用;
-
调用该函数不仅创建新会话,有如下额外效果:
- 调用进程成为会话的首领,该进程是新会话的唯一成员;
- 新建一个进程组,调用进程成为该组的首领;
-
所谓会话ID(SID)等于会话首领所在的进程组的PGID,用getsid函数读取;
-
-
用ps命令查看进程关系
$ps-o pid,ppid,pgid,sid,comm|less PID PPID PGID SID COMMAND #PPID为父进程 1943 1942 1943 1943 bash 2298 1943 2298 1943 ps 2299 1943 2298 1943 less
- 结果示意图
系统资源限制
-
Linux系统资源限制可以通过如下一对函数来读取和设置
#include<sys/resource.h> int getrlimit(int resource,struct rlimit*rlim); int setrlimit(int resource,const struct rlimit*rlim);
- resource参数指定资源限制类型;
- rlim参数是rlimit结构体类型的指针,描述资源级别和限制;
- rlim_cur成员指定资源的软限制,是一个建议性的、最好不要超越的限制;
- rlim_max成员指定资源的硬限制,硬限制一般是软限制的上限;
-
可以使用ulimit命令修改当前shell环境下的资源限制;
改变工作目录和根目录
-
一般来说,Web服务器的逻辑根目录并非文件系统的根目录“/”,而是站点的根目录/var/www/;
-
获取进程当前工作目录,改变进程工作目录,改变进程根目录的函数如下
#include<unistd.h> char*getcwd(char*buf,size_t size); int chdir(const char*path); int chroot(const char*path);
- chroot并不改变进程的当前工作目录,因此还需调用chdir切换至新的目录;
服务器程序后台化
-
库函数
#include<unistd.h> int daemon(int nochdir,int noclose);
- nochdir参数用于指定是否改变工作目录,若为0则工作目录将被设置为“/”(根目录);
- noclose参数为0时,标准输入、标准输出和标准错误输出都被重定向到/dev/null文件,否则依然使用原来的设备。