1.守护进程:在后台运行,且不受终端控制的一种进程。
2.通过ps axj | more指令可以查看到Linux下的守护进程
[root@localhost 进程组]# ps axj | more
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
0 1 1 1 ? -1 Ss 0 0:03 /sbin/init
0 2 0 0 ? -1 S 0 0:00 [kthreadd]
2 3 0 0 ? -1 S 0 0:00 [migration/0]
2 4 0 0 ? -1 S 0 0:02 [ksoftirqd/0]
2 5 0 0 ? -1 S 0 0:00 [stopper/0]
2 6 0 0 ? -1 S 0 0:41 [watchdog/0]
2 7 0 0 ? -1 S 0 0:37 [events/0]
2 8 0 0 ? -1 S 0 0:00 [events/0]
2 9 0 0 ? -1 S 0 0:00 [events_long/0]
2 10 0 0 ? -1 S 0 0:00 [events_power_ef]
2 11 0 0 ? -1 S 0 0:00 [cgroup]
2 12 0 0 ? -1 S 0 0:00 [khelper]
可以看到:守护进程的TPGID为-1,也就是TPGID为-1的为守护进程
因为守护进程脱离终端的控制,一方面因为让父进程退出,就会使得当前终端可以执行其它的指令,而之后其它的操作都让子进程去执行,让子进程已一种僵尸状态来执行,就可以达到脱离终端的目的。另一方面,需要创建新的会话,而创建会话的进程不能是组长进程,让父进程创建一个子进程,那么子进程一定不是组长进程。
因为子进程继承了父进程的一些信息,包括会话相关的消息,子进程必须要脱离父进程所在的会话,必须创建新的会话,让子进程变为新会话的话首进程
为了防止僵尸进程的出现
因为子进程以父进程为模板,那么子进程就会和父进程处在同一个工作目录下,所以需要改变子进程的工作目录
因为子进程是以父进程为模板,那么子进程就有和父进程一样的文件描述符表,父进程打开的文件,子进程也能操作,所以需要将文件描述符重定向,重定向至”/dev/null/”,这个目录相当于一个垃圾桶
因为创建文件时,文件创建掩码会屏蔽掉一些权限对应的位,所以需要重建文件创建掩码
#include
#include
#include
#include
#include
#include
#include
void MyDaemon()
{
//7.屏蔽umask
umask(0);
//1.创建一个子进程
pid_t pid = fork();
if(pid < 0)
{
perror("fork");
}
else if(pid > 0)
{
//2.让父进程退出
exit(0);
}
//3.子进程调用setsid,创建一个新的会话,
pid_t ret = setsid();
if(ret < 0)
{
perror("setsid");
}
//4.忽略掉SIGCHLD信号,忽略SIGHUP信号
signal(SIGCHLD,SIG_IGN);
signal(SIGHUP,SIG_IGN);
//5.修改工作目录为“/”
if(chdir("/") < 0)
{
perror("chdir");
}
//6.重定向文件描述符
int fd = open("/dev/null",O_RDWR);
dup2(fd,0);
dup2(fd,1);
}
int main()
{
MyDaemon(); //调用该函数之后就会使得main进程变为守护进程
while(1)
{
sleep(1);
}
return 0;
}
运行结果:(可以看到当前进程mydaemon的TPGID为-1,说明为守护进程)
[root@localhost 进程组]# ps axj | head -n 1 && ps axj | grep mydaemon | grep -v grep
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
1 28482 28482 28482 ? -1 Ss 0 0:00 ./mydaemon
1.通过daemon函数
(1)相关参数
#include
int daemon(int nochdir, int noclose);
//nochdir为0表示将工作目录变为"/"
//noclose为0表示将文件描述符重定向至"/dev/null"
(2)代码:
#include
#include
int main()
{
daemon(0,0);
while(1)
{
sleep(1);
}
return 0;
}
(3)运行结果:(可以看到进程mydaemon2变为守护进程)
[root@localhost 进程组]# ps axj |head -n 1 && ps axj | grep mydaemon2 | grep -v grep
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
1 29063 29063 29063 ? -1 Ss 0 0:00 ./mydaemon2
2.通过nohup指令(该指令与编程语言无关,适用任意一种语言)
(1)nohup 后面加上进程名 再加上&
(2)使用:
#include
#include
int main()
{
int i = 0;
for(;i<10;++i)
{
printf("%d\n",i);
sleep(1);
}
return 0;
}
将其变为守护进程:
[root@localhost 进程组]# nohup ./mydaemon3 &
[2] 29367
此时会在当前目录下生成一个nohup.out文件,但是显示下面这句话,表示权限不够,也就是没有可执行权限
[root@localhost 进程组]# nohup: ignoring input and appending output to `nohup.out'
通过chmod +x可以给某个文件加上可执行权限,此时运行结果如下:(可以看到mydaemon3进程的运行结果显示在nohup.out文件里)
[root@localhost 进程组]# chmod +x nohup.out
[2]+ Done nohup ./mydaemon3
[root@localhost 进程组]# cat nohup.out
0
1
2
3
4
5
6
7
8
9