Linux系统编程-进程(三):守护进程【Daemon Process(精灵进程)】【Linux 中的后台服务进程,独立于控制终端】
2023-09-27 14:20:40 时间
一、守护进程介绍
守护进程(Daemon Process),也就是通常说的 Daemon 进程(精灵进程),是 Linux 中的后台服务进程。它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。一般采用以d结尾的名字。
守护进程是个特殊的孤儿进程,这种进程脱离终端,为什么要脱离终端呢?之所以脱离于终端是为了避免进程被任何终端所产生的信息所打断,其在执行过程中的信息也不在任何终端上显示。
由于在 Linux 中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依附于这个终端,这个终端就称为这些进程的控制终端,当控制终端被关闭时,相应的进程都会自动关闭。
Linux 的大多数服务器就是用守护进程实现的。比如,Internet 服务器 inetd,Web 服务器 httpd 等。
二、守护进程模型
1) 创建子进程,父进程退出(必须)
- 所有工作在子进程中进行形式上脱离了控制终端
2) 在子进程中创建新会话(必须)
- setsid()函数
- 使子进程完全独立出来,脱离控制
3) 改变当前目录为根目录(不是必须)
- chdir()函数
- 防止占用可卸载的文件系统
- 也可以换成其它路径
4) 重设文件权限掩码(不是必须)
- umask()函数
- 防止继承的文件创建屏蔽字拒绝某些权限
- 增加守护进程灵活性
5) 关闭文件描述符(不是必须)
- 继承的打开文件不会用到,浪费系统资源,无法卸载
6) 开始执行守护进程核心工作(必须)
守护进程退出处理程序模型
三、守护进程参考代码
写一个守护进程, 每隔2s获取一次系统时间, 将这个时间写入到磁盘文件:
/*
* time_t rawtime;
* time ( &rawtime ); --- 获取时间,以秒计,从1970年1月一日起算,存于rawtime
* localtime ( &rawtime ); //转为当地时间,tm 时间结构
* asctime() // 转为标准ASCII时间格式:
*/
void write_time(int num)
{
time_t rawtime;
struct tm * timeinfo;
// 获取时间
time(&rawtime);
#if 0
// 转为本地时间
timeinfo = localtime(&rawtime);
// 转为标准ASCII时间格式
char *cur = asctime(timeinfo);
#else
char* cur = ctime(&rawtime);
#endif
// 将得到的时间写入文件中
int fd = open("/home/edu/timelog.txt", O_RDWR | O_CREAT | O_APPEND, 0664);
if (fd == -1)
{
perror("open error");
exit(1);
}
// 写文件
int ret = write(fd, cur, strlen(cur) + 1);
if (ret == -1)
{
perror("write error");
exit(1);
}
// 关闭文件
close(fd);
}
int main(int argc, const char* argv[])
{
pid_t pid = fork();
if (pid == -1)
{
perror("fork error");
exit(1);
}
if (pid > 0)
{
// 父进程退出
exit(1);
}
else if (pid == 0)
{
// 子进程
// 提升为会长,同时也是新进程组的组长
setsid();
// 更改进程的执行目录
chdir("/home/edu");
// 更改掩码
umask(0022);
// 关闭文件描述符
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
// 注册信号捕捉函数
//先注册,再定时
struct sigaction sigact;
sigact.sa_flags = 0;
sigemptyset(&sigact.sa_mask);
sigact.sa_handler = write_time;
sigaction(SIGALRM, &sigact, NULL);
// 设置定时器
struct itimerval act;
// 定时周期
act.it_interval.tv_sec = 2;
act.it_interval.tv_usec = 0;
// 设置第一次触发定时器时间
act.it_value.tv_sec = 2;
act.it_value.tv_usec = 0;
// 开始计时
setitimer(ITIMER_REAL, &act, NULL);
// 防止子进程退出
while (1);
}
return 0;
}
相关文章
- 利用forever在Linux上实现Node.js项目自启动
- Linux 上 GDM 登录界面如何适应高分屏
- 如何更改 Linux 的 I/O 调度器
- 【Linux】获取当前时间
- Linux 内核提交和控制一个 urb
- Linux 内核控制 urb
- linux 添加 service 服务并自动添加 chkconfig 启动级别
- 每天一个linux命令(50):crontab命令
- linux系统编程:进程控制(fork)
- 教你如何在VMware上创建虚拟机以及安装Linux操作系统
- 【正点原子MP157连载】 第十一章 触摸按键控制LED灯实验【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7
- 【正点原子Linux连载】第十五章 Qt控制BEEP 摘自【正点原子】I.MX6U嵌入式Qt开发指南V1.0.2
- arm-linux内核start_kernel之前启动分析(1)-接过bootloader的衣钵
- Linux系统编程_8_进程控制之fork_wait_waitpid函数
- windows linux 双系统默认启动windows 的几种方法
- Linux 使用Mycat实现读写分离(基于Mysql的读写分离)
- linux下库的使用--动态库