2.31、守护进程(2) 1.守护进程的创建步骤 2.什么情况下子进程不会继承父进程的组ID 3.哪些操作会导致子进程的组ID发生改变 4.kill怎么杀掉守护进程的 实现守护进程
1.守护进程的创建步骤
执行一个 fork()
,之后父进程退出,子进程继续执行。 使用子进程的目的是防止创建会话的进程为首进程,创建守护进程(daemon)时,通常需要让该进程摆脱与控制终端的关联,即让它成为一个无终端进程。首进程创建会话会导致新建会话的组id与之前存在的组id相同。 子进程调用 setsid()
开启一个新会话。 清除进程的 umask
以确保当守护进程创建文件和目录时拥有所需的权限。 修改进程的当前工作目录,通常会改为根目录(/)
。 关闭守护进程从其父进程继承而来的所有打开着的文件描述符。 在关闭了文件描述符0、1、2
之后,守护进程通常会打开/dev/null
并使用dup2()
使所有这些描述符指向这个设备。 核心业务逻辑
2.什么情况下子进程不会继承父进程的组ID
当父进程使用setpgid()
系统调用将自己加入到一个新的进程组中,而子进程在此之后被创建时,子进程不会继承父进程的PGID
,而是创建一个新的进程组,并将自己作为该进程组的领导进程,PGID
与PID
相同。 当父进程在创建子进程之前调用了setsid()
系统调用创建了一个新的会话,子进程也会在此之后创建一个新的会话,并成为该会话的领导进程,PGID
与PID
相同。 当父进程使用CLONE_NEWPID
或CLONE_NEWUSER
等Linux
特有的命名空间创建了一个新的进程隔离环境时,子进程不会继承父进程的PGID
。
3.哪些操作会导致子进程的组ID发生改变
调用setpgid()
系统调用将子进程加入到一个新的进程组中,子进程的PGID
将被设置为指定的PGID
。 在子进程中调用setpgid()
系统调用将自己加入到一个新的进程组中,子进程的PGID
将被设置为指定的PGID
。 在子进程中调用setsid()
系统调用创建一个新的会话,子进程将成为该会话的领导进程,并且PGID
与PID
相同。 在子进程中调用exec()
系统调用执行另一个程序,新程序的PGID
可能与旧程序不同。
4.kill怎么杀掉守护进程的
在Linux
系统中,kill
命令可以向指定进程发送信号。这个过程是通过进程ID(PID)
来实现的,而不是通过控制终端。即使守护进程没有控制终端,它也有一个PID
,其他进程可以使用这个PID
向它发送信号,其中包括kill
命令发送的信号。
实现守护进程
# include <stdio.h>
# include <sys/types.h>
# include <unistd.h>
# include <sys/stat.h>
# include <sys/time.h>
# include <signal.h>
# include <time.h>
# include <fcntl.h>
# include <string.h> void work ( )
{ time_t tm = time ( NULL ) ; struct tm * loc = localtime ( & tm) ; char * str = asctime ( loc) ; int fd = open ( "time.txt" , O_CREAT | O_APPEND | O_RDWR, 0664 ) ; write ( fd, str, strlen ( str) ) ; } int main ( )
{ pid_t proPid = fork ( ) ; if ( proPid > 0 ) { return 0 ; } pid_t sePid = setsid ( ) ; umask ( 022 ) ; chdir ( "/home/nowcoder/" ) ; int fd = open ( "/dev/null" ) ; dup2 ( fd, STDIN_FILENO) ; dup2 ( fd, STDOUT_FILENO) ; sup2 ( fd, STDERR_FILENO) ; struct sigaction act; act. sa_flags = 0 ; sigemptyset ( & act. sa_mask) ; act. sa_handler = work; sigaction ( SIGALRM, & act, NULL ) ; struct itimerval val; val. it_value. tv_sec = 3 ; 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 ) { sleep ( 2 ) ; } return 0 ;
}