守护进程的特点
1.生存期较长 往往只有系统关机时会结束
2.在后台运行提供服务
3.独立于控制终端 也就是没有控制终端
4.能周期性地执行任务 或者 等待处理某些发生的事件
5.该类进程的名字常以字母d结尾
守护进程是一个脱离终端的孤儿进程
脱离终端可以避免被任何终端产生的信息打断
守护进程在执行过程中产生的信息不会在任何终端上显示
补充终端的概念
Linux中 每一个系统与用户进行交流的界面被称为终端
当用户通过终端登录系统后 会运行一个Shell进程
这个终端会成为Shell进程的控制终端
每一个从此终端开始运行的进程都会依附于这个终端
这个终端就被称为这些进程的控制终端
当控制终端被关闭时 相关的依附进程会自动结束
执行命令 ps aux
在 TTY 一列中可以看到程序依赖的终端
有依赖通常表现为 pts/终端的id (一个数字)
没有依赖的终端常表现为 ? (一个问号)
补充会话的概念
会话是一个或多个进程组的集合 一个会话可以有一个控制终端
与控制终端建立连接的会话首进程被称为控制进程
如果终端断开连接 控制进程(也就是会话首进程)会收到挂断信号并执行操作
一个会话只有一个前台进程组 剩下的都是后台进程组
重点:新会话的建立会丢弃原有的控制终端 新会话将没有控制终端
如何使终端关闭且用户退出登录后 进程仍然运行?
设计实现一个进程 每2s获取一下系统时间
操作步骤
1.创建子进程 父进程退出
子进程一定不是进程组的组长进程 只有非组长进程才能创建新会话
父进程退出后 启动父进程的终端会认为进程已经终止
2.创建新的会话新会话的建立会丢弃原有的控制终端 新会话将没有控制终端
子进程调用setid() 称为会话的会长 进程组的组长
3.改变当前工作目录子进程调用chdir() 防止程序的工作目录被卸载 比如U盘拔出
4.设置权限掩码调用fork()生成的子进程会继承父进程的文件权限掩码 会限制最大权限
调用umask() 防止继承的文件拒绝某些权限
5.关闭文件描述符子进程继承的文件 若打开却不使用 会浪费系统资源
6.执行核心的任务
代码如下
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
//创建守护进程
int main(void)
{
//0.初始化两个返回值
int ret = -1;
pid_t pid = -1;
//1.创建子进程 父进程退出
pid = fork();
if(-1 == pid)
{
perror("fork");
return 1;
}
if(pid > 0)
{
exit(0);
}
//2.创建新的会话 完全脱离控制终端
pid = setsid();
if(-1 == pid)
{
perror("setsid");
return 1;
}
//3.改变当前工作目录
ret = chdir("/");
if(-1 == ret)
{
perror("chdir");
return 1;
}
//4.设置权限掩码 不屏蔽任何权限
umask(0);
//5.关闭文件描述符
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
//6.执行核心的任务
while(1)
{
//每隔2s输出当前时间到文件中
//系统调用 效果相当于在Shell中执行命令 并实现重定向
system("date >> /home/boywithoutua/5.3/log.txt");
sleep(2);
}
return 0;
}
动态查看(出现变化就提示)文件内容的命令:tell -f 文件名