七、Linux服务器程序规范
1.大部分后台进程都在/var/log目录下拥有自己的日志目录。
2.绝大多数服务器程序都有配置文件,并存放在/etc目录下。
3.Linux服务器进程通常会在启动的时候生成一个PID文件并存入/var/run目录中,以记录该后台进程的PID。
4.大部分服务器必须以root身份启动但不能以root身份运行。
5.Linux提供一个守护进程来处理系统日志——syslogd,现在使用的已经是它的升级版——rsyslogd。
rsyslogd守护进程既能接收用户进程输出的日志,又能接收内核日志。
#include <syslog.h>
// 应用程序使用syslog函数与rsyslogd守护进程通信。
void syslog(int priority, const char* message, ...);
// 下面这个函数可以改变syslog的默认输出方式:
void openlog(const char* ident, int logopt, int facility);
- ident指定的字符串将被添加到日志消息的日期和时间之后,它通常被设置为程序的名字。
- logopt参数对后续syslog调用的行为进行配置。
- facility参数可用来修改syslog函数中的默认设施值。
// 下面这个函数用于设置syslog的日志掩码
int setlogmask(int maskpri);
- maskpri参数指定日志掩码值。
// 最后不要忘了关闭日志功能:
void closelog();
6.下面这一组函数可以获取和设置当前进程的真实用户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
- 一个进程拥有两个用户ID:UID和EUID。EUID存在的目的是方便资源访问:它使得运行程序的用户拥有该程序的有效用户的权限。
// 如果将以root身份启动的进程切换为以一个普通用户身份运行。
static bool switch_to_user(uid_t user_id, gid_t gp_id)
{
// 先确保目标用户不是root
if(0 == user_id && 0 == gp_id)
return false;
// 确保当前用户是合法用户:root或者目标用户
gid_t gid = getgid();
uid_t uid = getuid();
if((0 != gid || 0!= uid) && (gid != gp_id || uid != user_id))
return false;
// 如果不是root,则已经是目标用户
if(0 != uid)
return false;
// 切换到目标用户
if(setgid(gp_ud) < 0 || setuid(user_id) < 0)
return false;
return true;
}
7.Linux系统资源限制可以用个如下一对函数来读取和设置:
#include <sys/resource.h>
int getrlimit(int resource, struct rlimit *rlim);
int setrlimit(int resource, const struct rlimit *rlim);
struct rlimit
{
rlimt_t rlim_cur; // 指定资源的软限制
rlimt_t rlim_max; // 指定资源的硬限制
}
此外,我们可以使用ulimit命令修改当前shell环境下的资源限制(软限制或/和硬限制)。
8.高性能服务器应该避免不必要的数据复制,尤其是当数据复制发生在用户代码和内核之间的时候。例如可以用零拷贝函数去实现某些功能。
用户代码内部(不访问内核)的数据复制也是应该避免的。例如,使用共享内存来共享这些数据,而不是使用管道或消息队列传递数据。
9.strace命令能跟踪程序执行时调用的系统调用和接收到的信号。
10.两种高效的管理定时器的容器:时间轮和时间堆。
Linux提供了三种定时方法,它们是:
- socket选项SO_RCVTIMEO和SO_SNDTIMEO
- SIGALRM信号
- I/O复用系统调用的超时参数