1.守护进程的
概念:系统中的后台进程,周期性的执行某些任务,或者等待某个事件的发生,不会随用户的注销而退出
特点:后台服务进程,不会显示在终端,除了关机和kill,守护进程是不会死的
独立于控制终端
周期性执行某任务
不受用户登录注销影响
守护进程一般采用以d结尾的名字(服务)
2.进程组
1.进程组的长?
组里面的第一进程
进程组的ID==进程组的组长的ID
3.会话:多个进程组组成的组织叫会话
1.创建一个会话注意事项
不能是进程组长
创建会话的进程称为新进程组的组长
创建出的新会话会丢弃原有的控制终端
一般步骤:先fork,父进程死。儿子执行创建会话操作
2.创建一个会话:pid_t setsid(void)
3.获取进程所属的会话ID:pid_t getsid(pid_t pid)
4.创建守护进程模型
1.fork子进程,父进程退出,必须做
2.子进程创建新会话,必须做,setsid()函数
3.改变当前工作目录chdir,不是必须的,增强程序的健壮性
4.重设文件掩码
原因:子进程会继承父进程的掩码
目的:增加子进程程序操作的灵活性
umask(0);
5.关闭文件描述符,不是必须的
子进程脱离终端了,所以需要关闭标准输入,标准输出,标准错误输出
目的:释放资源
6.执行核心工作,必须的
5.得到当前时间函数,得到的时间是time_t类型的
函数原型:time_t time(time_t *tloc)
6.得到的时间格式化
上面的那个函数得到的是时间是time_t类型,所以我们需要把得到的time_t类型的时间格式化成我们认识的格式
函数原型:char * ctime(const time_t *time)
下面看一个守护进程最简单的代码:
7 int main()
8 {
9 pid_t pid = fork();
10 //创建出子进程,让父进程死
11 if(pid > 0)
12 {
13 exit(0);
14 //kill(getpid(),SIGKILL);
15 //raise(SIGKILL);
16 //abort(); 这三个函数都可以杀死父进程
17 }
18 else
19 {
20 //获取会话id,成为新进程组的组长
21 setsid();
22 while(1);
23 }
24
25 return 0;
26 }
这就创建出了一个守护进程,在后台运行,不现实在终端
但是可以用ps -aux可以看到这个进程在后台运行
这就说明守护进程在运行,除非你关机或者kill它,否在它会一直存在
接下来看一个题目:写一个守护进程,每隔两秒获取一次系统时间,并将时间写到文件中。
那我们就要按上面的流程来写代码了
1 #include<stdio.h>
2 #include<signal.h>
3 #include<unistd.h>
4 #include<stdlib.h>
5 #include<time.h>
6 #include<fcntl.h>
7 #include<string.h>
8 #include<sys/time.h>
9
10 void dowork(int n)
11 {
12 //获取当前时间,写到磁盘中去
13 time_t curtime;
14 time(&curtime);
15 //格式化时间
16 char *ptr = ctime(&curtime);
17 //写到文件中去
18 int fd = open("file",O_CREAT|O_WRONLY | O_APPEND,0664);
19 write(fd,ptr,strlen(ptr) + 1);
20 close(fd);
21 }
22
23 int main()
24 {
25 pid_t pid = fork();
26 if(pid > 0)
27 {
28 exit(0);
29 }
30 else if(pid == 0)
31 {
32 //子进程成为新的会长,脱离终端,成为守护进程
33 setsid();
34 //重新设置文件掩码
35 umask(0);
36 //关闭文件描述符
37 close(0);
38 close(1);
39 close(2);
40
41 //执行核心的工作
42
43 //注册信号捕捉
44 struct sigaction act;
45 act.sa_flags = 0;
46 act.sa_handler = dowork;
47 sigemptyset(&act.sa_mask);
48 sigaction(SIGALRM,&act,NULL);
49
50
51 //创建一个定时器
52 struct itimerval val;
53 //第一次触发的时间
54 val.it_value.tv_usec = 0;
55 val.it_value.tv_sec = 2;
56 //循环周期
57 val.it_interval.tv_usec = 0;
58 val.it_interval.tv_sec = 1;
59 setitimer(ITIMER_REAL,&val,NULL);
60
61
62 while(1);
63
64 }
65 return 0;
66 }
我们运行一下可以看到系统出现了一个file文件,每隔1秒将当前时间写入文件中
程序仍然在后台运行,那么我们接下来看一下file文件,每一秒写一次
上面提到了守护进程的特性,除非关机或者kill这个守护进程,否则它会一直运行。所以如果不杀死我们这个程序,那么我们这个程序就会将磁盘写满,所以我们需要杀死这个守护进程。