进程的
1. 守护进程的特点
○ 后台服务进程
○ 独立于控制终端
○ 周期性执行某任务
○ 不受用户登录注销影响
○ 一般采用以d结尾的名字(服务)
2. 进程组
○ 进程的组长?
§ 组里边的第一进程
§ 进程组的ID == 进程组的组长的ID
○ 进程组组长的选则
§ 进程中的第一个进程
○ 进程组ID的设定
§ 进程组的id就是组长的进程ID
3. 会话 - 多个进程组
○ 创建一个会话注意事项:
§ 不能是进程组长
§ 创建会话的进程成为新进程组的组长
§ 有些linux版本需要root权限执行此操作(ubuntu不需要)
§ 创建出的新会话会丢弃原有的控制终端
§ 一般步骤:先fork, 父亲死, 儿子执行创建会话操作(setsid)
○ 获取进程所属的会话ID
§ pid_t getsid(pid_t pid);
○ 创建一个会话
§ pid_t setsid(void);
4. 可以使用ps ajx来查看进程组ID和会话ID
5. 创建守护进程模型
○ fork子进程,父进程退出
§ 必须
子进程继承了父进程的进程组ID, 但具有一个新的进程ID,这样就保证了子进程不是一个进程组的组长ID,这对于下面要做的setsid函数的调用是必要的前提条件
○ 子进程创建新会话
§ 必须
§ setsid();
▪ 调用这个函数以后:
a 该进程成为新会话的首进程
b 成为一个新进程组的组长进程
c 没有终端控制
○ 改变当前工作目录chdir
§ 插了一个U盘,a.out, 在U盘目录中启动a.out
§ a.out启动过程中,U盘拔掉了
§ 不是 必须的。
○ 重设文件掩码 mode & ~umask
§ 子进程会继承父进程的掩码
§ 增加子进程程序操作的灵活性
§ umask(0);
§ 不是必须的
○ 关闭文件描述符
close(0);
close(1)
close(2)
释放资源
不是必须的
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <fcntl.h>
#include <sys/wait.h>
int fd;
void signalhandler(int signo)
{
time_t tm;
time(&tm);
char *p = ctime(&tm);
write(fd, p, strlen(p));
}
int main(int argc, char *argv[])
{
pid_t pid;
pid = fork();
if (pid > 0 || pid < 0)
{
exit(0);
}
setsid();
chdir("./");
umask(0);
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
fd = open("./text.log", O_RDWR | O_CREAT, 0777);
if (fd < 0)
{
perror("open error");
return -1;
}
struct sigaction act;
act.sa_handler = signalhandler;
sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask, SIGALRM);
act.sa_flags = 0;
sigaction(SIGALRM, &act, NULL);
struct itimerval tm;
tm.it_interval.tv_sec = 2;
tm.it_interval.tv_usec = 0;
tm.it_value.tv_sec = 3;
tm.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &tm, NULL);
while (1)
{
sleep(2);
}
close(fd);
return 0;
}
![这里写图片描述](https://img-blog.csdn.net/20171024021855569?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvUG9pc3g=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)