1、进程组组长:进程组的首个进程,除了进程组id = 进程组组长id之外,没什么特权前文我们通过nohup指令 + &创造了一个可以持续在后台运行的进程但事实上nohup指令还是更侧重于临时测试的时候使用,原因在于此时的进程还没有真正不受会话影响,还不是一个真正意义上的守护进程nohup只是让进程忽略会话结束时发出的SIGHUP信号,但此时的进程仍是属于当前会话的,仍然会受会话的管理者控制所以,要想真正创建一个一直运行不受任何影响的进程,你就必须退出当前会话这个时候就需要介绍一个系统调用接口setsid()setsid()的作用是创建一个新的会话,并让调用进程成为这个新会话的管理者、新进程组的组长注意调用setsid()后,这个调用进程会变成新会话的管理者,那么如果这个调用进程在调用setsid()函数之前就是一个进程组的组长呢?那么此时就会出现一个进程是两个进程组的组长的问题,这在Linux中是不允许的所以在调用setsid()函数之前,我们需要确保当前的进程不是某个进程组的组长由于父子进程同属于一个进程组,父进程一定先于子进程创建如果父进程是进程组组长,那么子进程一定不是进程组组长;如果父进程不是进程组组长,说明是父进程的父进程或者更上面是进程组组长,其子进程一定不是进程组组长所以可以使用当前进程fork()之后的子进程作为我们运行代码的进程这里提一个细节,父进程通常会等待子进程的退出,也就说父进程在某种程度上管理着子进程,而父进程又在原来的会话里面,原来的会话会影响当前的父进程进而影响你的子进程,所以最好让父进程直接退出,让子进程成为孤儿进程由init接管id = fork();if (id > 0){ // 父进程 exit(0);}// 子进程setsid();
注意,一个会话是可以不依赖于终端的并且刚开始创建是没有终端的,但是会话的管理者有使用终端的权力但是不能肯定接管的进程不会打开终端,所以最好让当前会话没有管理者,使之永远不可能与终端交互所以再次使用fork(),以防止进程误触终端,同时让父进程退出使得当前会话没有管理者// 第一次fork() => 使之不是进程组组长pid_t id = fork();if (id > 0){ // 父进程 => 原来的会话会影响当前的父进程进而影响你的子进程 // 所以最好让父进程直接退出 exit(0);}// 子进程setsid();// 第二次fork() => 使之不是会话管理者id = fork();if (id > 0){ // 父进程 => 使会话没有管理者 exit(0);}// 子进程
此时此刻,一个基本的守护进程(daemon)就完成了如果你要更改进程的工作目录,可以使用chdir()函数;如果你要设置进程创建文件的mask值,可以使用umask()函数;如果你不使用一些文件描述符,可以使用close()函数关掉大家如果有什么感兴趣的内容,欢迎私信或者评论区留言