守护进程
特点:
- 后台服务程序;
- 独立于控制终端(不依赖终端,在后台运行);
- 周期性执行某任务;
- 不受用户登录注销影响;
- 一般以d结尾的名字(服务)。
进程组
进程组的组长:
- 组里的第一个进程;
- 进程组ID 等于 进程组组长的D。
会话
会话:多个进程组。
创建一个会话注意事项:
- 不能是进程组组长;
- 创建会话的进程称为新进程组组长;
- 需要root权限执行此操作;
- 创建出的新会话丢弃原有控制终端;
- 一般步骤fork()、父亲死、儿子执行创建会话操作。
获取进程所属会话ID:
pid_t getsid(pid_t pid);
创建一个会话:
pid_t setsid(void);
创建守护进程模型
fork()
子进程,父进程退出;- 子进程创建新会话
setsid(void)
; - 改变当前工作目录
chdir
(切换至一个不可卸载的目录,不是必须的。如,不可放在U盘。)。 - 重设文件掩码(因为子进程会继承父进程的掩码。增加程序灵活性。不是必须。eg:
umask(0)
); - 关闭文件描述符(关闭0、1、2,释放资源,不是必须。);
- 执行核心工作(必须)。
例子
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<signal.h>
#include<fcntl.h>
#include<sys/time.h>
#include<time.h>
#include<string.h>
void dowork(int signo) {
time_t curtime;
//获取时间
time(&curtime);
//格式化时间
char* ptime = ctime(&curtime);
int fd = open("/home/kiosk/time.txt", O_CREAT|O_WRONLY|O_APPEND, 0664);
write(fd, ptime, strlen(ptime) + 1);
}
int main(void) {
pid_t pid = fork();
if(pid == -1) {
} else if( pid > 0) {
exit(1);
} else {
setsid();
chdir("/home/kisok");
umask(0);
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
struct sigaction act;
act.sa_handler = dowork;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGALRM, &act, NULL);
struct itimeval val;
val.it_value.tv_sec = 2;
val.it_value.tv_usec = 0;
val.it_interval.tv_sec = 2;
val.it_interval.tv_usec = 0;
setitimer(ITIMER_REAL,&val,NULL);
//保证子进程不退出
while(1) {
}
}
return 0;
}