文章目录
- 1、日志
- 1.1、syslog()函数
- 2、用户信息
- 2.1、UID、EUID、GID、EGID
- 3、进程间关系
- 3.1、进程组
- 3.2、会话
- 4、服务器程序后台化(守护进程)
1、日志
Linux提供一个守护进程rsyslogd
来处理系统日志,系统日志中包括用户进程产生的日志以及内核日志。
- 用户进程调用
syslog
生成系统日志,并将内容输出到socket类型的文件/dev/log
中 - 内核日志是由
priontk
打印到内核的环状缓存中并直接映射到/proc/kmsg
中
rsyslogd
从以上两个文件中接收到输入的日志后,会把它们输出到指定的日志文件,rsyslogd
的主配置文件为/etc/rsyslog.conf
,通过修改主配置文件可以修改不同信息的存放路径,部分默认情况下:
- 调试信息保存到
/var/log/debug
- 普通信息保存到
/var/log/message
- 内核消息保存到
/var/log/kern.log
两种日志信息的传递过程如下所示
1.1、syslog()函数
#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 6 //信息
#define LOG_DEBUG 7 //调试
下面函数设置日志掩码,使得日志级别大于日志掩码的日志被忽略,从而使得调试信息在发布之后自动删除。
int setlogmask(int maskpri);
使用下面函数可以关闭日志功能
void closelog();
2、用户信息
2.1、UID、EUID、GID、EGID
在Linux当中一个进程(程序)拥有四个ID:真实用户UID
、有效用户EUID
、真实组GID
和有效组EGID
。针对UID
以及EUID
来看:
UID
:指的是登录该进程的用户UID
EUID
:指的是当前用户执行操作时,该用户有没有权限去执行该操作,要看此时的有效用户是否有权限去执行操作
相关函数如下:
#include <sys/types.h>
#include <unistd.h>
uid_t getuid();
uid_t geteuid();
gid_t getgid();
gid_t getegid();
int setuid();
int seteuid();
int setgid();
int setegid();
3、进程间关系
3.1、进程组
每个进程组都有一个首领进程,其PGID
和PID
相同,进程组会一直存在,直到其中的所有进程都退出或者加入到其他进程组。
#include <unistd.h>
pid_t getpgid(pid_t pid);
//成功返回进程pid所在的进程组pgid,失败返回-1并设置error
int setpgid(pid_t pid, pid_t pgid);
一个进程只能设置自己或其子进程的PGID
,上面的函数是将PID
为变量pid的进程的PGID
设置为变量pgid,这时有以下几种情况:
- 当pid==pgid时,则由pid的进程作为其进程组的首领进程。
- 当pid==0时,表示设置当前的
PGID
为变量pgid。 - 当pgid==0时,则使用变量pid作为目标
PGID
。
3.2、会话
一些有关联的进程组会形成一个会话。
#incclude <unistd.h>
//创建会话
pid_t setsid(void);
//函数成功返回新进程组的PGID,失败返回-1并设置error
该函数由进程组的首领调用会产生一个错误,而由非首领的进程调用,该进程在创建一个新会话的同时,会有以下效果:
- 调用进程成为会话的首领,此时该进程是新会话的唯一成员
- 新建一个进程组,其
PGID
就是进程的PID
,调用进程成为该组的首领 - 调用进程将甩开终端(如果存在终端的话)
在linux中并没有会话ID的概念,认为会话ID等于进程组的PGID,并且有以下函数读取会话ID(SID):
#include <unistd.h>
pid_t getsid(pid_t pid);
4、服务器程序后台化(守护进程)
#include <unistd.h>
int daemon(int nochdir, int noclose);
daemon的作用是可以将当前进程转化为后台进程
如果nochdir
为零,daemon()
将进程的当前工作目录更改为根目录/
; 否则,当前工作目录保持不变。
如果noclose
为零,daemon()
将标准输入,标准输出和标准错误重定向到/dev/null
; 否则,不会对这些文件描述符进行更改。(参数为0时有效)
返回值:
deamon()
调用了fork()
,如果fork成功,那么父进程就调用_exit()
退出,因此只能通过子进程看到进一步的错误。如果成功函数返回0,否则返回-1并设置errno。