进程的
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)
释放资源
不是必须的
/*************************************************************************
> File Name: maeom.c
https://github.com/chensongpoixs
> Created Time: Mon 23 Oct 2017 11:26:19 PM CST
************************************************************************/
#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[])
{
//PCB进程块 pid
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;
}
//设置signal信号事件
struct sigaction act;
//回调函数
act.sa_handler = signalhandler;
//清空信令集信令
sigemptyset(&act.sa_mask);
//设置信令
sigaddset(&act.sa_mask, SIGALRM);
act.sa_flags = 0;
//设置事件信令SIGALRM
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;
}