Linux服务器程序规范

日志

rsyslogd是常用的Linux日志系统,可以处理用户进程和内核日志。
用户进程调用syslog函数生成系统日志,输出到/dev/log中,rsyslogd监听该文件以获取用户进程的输出。具体见书 P 115 P_{115} P115
在这里插入图片描述

syslog

#include<syslog.h>
void syslog(int priority, const char* message, ...);

该函数采用可变参数来结构化输出,prioritiy是设施值和日志级别的按位或。设施值的默认值是LONG_USER,日志级别有:
在这里插入图片描述
另外openlog可以改变syslog的默认输出方式,从而结构化日志内容。

用户信息

UID, EUID, GID, EGID

大部分服务器需要以root身份启动,但不以root身份运行。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

切换用户

将以root身份启动的进程切换为普通身份运行

bool switch_to_user(uid_t user_id, gid_t gp_id) {
	if (user_id == 0 && gp_id == 0) {
		// user已经是root了
		return false;
	}
	gid_t gid = getgid();
	uid_t uid = getuid();
	// 确保当前用户只有两种状态:root或者目标用户
	if ((gid != 0 || uid != 0) && ((gid != gp_id || (uid != user_id)))) {
		return false;
	}
	// 已经是目标用户
	if (uid != 0) {
		return true;
	}
	// 切换到目标用户
	if (setgid(gp_id) < 0 || setuid(user_id) < 0) {
		return false;
	}
	return true;
}

进程间关系

进程组

pit_t getpgid(pid_t pid)返回进程所属的进程组的PGID
int setpgid(pid_t pid, pid_t pgid)将pid进程的进程组的PGID设置为pgid,如果pid和pgid相同,则该进程被设置为进程组首领。如果pid为0,则表示设置当前进程的PGID为pgid,如果pgid为0,则使用pid作为目标pgid。

系统资源限制

#include<sys/resource.h>
int getrlimit(int resource, struct rlimit* rlim);
int setrlimit(int resource, const struct rlimit* rlim);

strcut rlim{
	rlim_t rlim_cur;
	rlim_t rlim_max;
};

在这里插入图片描述

改变工作目录

#include<unistd.h>
char* getcwd(char* buf, size_t size);
int chdir(const char* path);

buf指向的内存用来存储当前工作目录的绝对路径名,其大小用size指定,如果当前工作目录的绝对路径长度超过了size(包含’\0’),则getcwd返回NULL。
如果buf为NULL且size非0,则getcwd在内部使用malloc动态分配内存,并将进程的当前工作目录存储在其中,这种情况我们需要自己释放这块内存。
getcwd成功时返回一个指向目标存储区的指针(buf‘指向的缓存区或自动分配的缓存区)。
chdir函数的path指定要切换到的目标目录。
改变进程根目录的函数时int chroot(const char* path)chroot不改变进程的当前工作目录,所以调用后依然需要使用chdir("/")来切换到新的根目录。切换根目录后之前打开的fd依然有效。

区别:chdir在当前工作目录切换,chroot可以改变根目录。

服务器程序后台化——守护进程

以守护进程进程的形式将服务器程序后台化。
守护进程:守护进程是运行在后台的一种生存期长的特殊进程。它独立于控制终端,处理一些系统级别任务。
如何实现

  • 创建子进程,终止父进程。方法是调用fork() 产生一个子进程,然后使父进程退出。
  • 调用setsid() 创建一个新会话。
  • 将当前目录更改为根目录。使用fork() 创建的子进程也继承了父进程的当前工作目录。
  • 重设文件权限掩码。文件权限掩码是指屏蔽掉文件权限中的对应位。
  • 关闭不再需要的文件描述符。子进程从父进程继承打开的文件描述符。
bool deamonize(){
	// 创建子进程,关闭父进程,以使程序在后台运行
	pid_t pid = fork();
	if(pid < 0){
		return false;
	}else if(pid > 0){
		exit(0);
	}
	// 设置文件权限掩码,当进程创建新文件(调用open)时,文件的权限将是mode & 0777;
	umask(0);
	pid_t sid = setsid();
	if(sid < 0)	return false;
	
	if((chdir("/")) < 0) return false;
	
	// 关闭标准输入输出设备和错误输出设备,并将标准输入输出、错误都定向到/del/null文件
	close(STDIN_FILENO);
	close(STDOUT_FILENO);
	close(STDERR_FILENO);
	
	open("/dev/null", O_RDONLY);
	open("/dev/null", O_RDWR);
	open("/dev/null", O_RDWR);
	// 关闭打开的文件描述符
	//...
	return true;
}

Linux有库函数

#include<unistd.h>
int daemon(int nochdir, int noclose);

nochdir指定是否改变工作目录,传递0则工作目录设置为’/’,否则继续使用当前工作根目录。
noclose为0时,标准输入输出错误将被定向到/dev/null文件,否则依然使用原来的设备。
函数调用成功返回0,失败返回-1.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值