一.进程组,会话
- PGID:进程组id,一条命令启动的所有进程及其子进程属于同一个进程组。一条指令中最先创建的进程就是组长,组id就是组长的PID。./启动的
- SID:会话id,每次登录Linux,操作系统给登录的用户提供一个bash和终端,一个bash和终端和一个会话绑定。第一个进程组的id就是会话id,一般来说,bash自成一个进程组,且最先创建,所以会话id一般是bash的PID。但守护进程就是个例外。
- TTY:终端设备名称
一个会话内部可以有很多个进程组,但只允许一个进程组在前台,所谓前台就是和终端,键盘相关。
如何把前台进程提到后台?
jobs查看当前会话的所有任务(进程组)。Ctrl + z将前台进程暂停,操作系统将前台进程提到后台,再把bash提到前台,这样我们就能输入指令了。接着bg + 任务号,使被暂停的进程在后台继续运行。
如何把后台进程提到前台?
首先要保证bash在前台以便接收命令,然后fg + 任务号,将后台进程提到前台。
二.守护进程
守护进程自成一个会话,该会话不和终端和bash关联,所以即便所有的终端都关闭,它也不会退出。
要求守护进程不能是进程组的组长,所以我们要创建子进程,必须fork创建子进程,然后让父进程退出,子进程不是组长,再把子进程设置为守护进程。
#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <fcntl.h>void Daemon(bool changeCwd)
{const char* path = "/";const char* devNull = "/dev/null";//1.忽略可能引起进程退出的信号signal(SIGCHLD, SIG_IGN);signal(SIGPIPE, SIG_IGN);//2.让进程不要当组长if (fork() > 0){exit(0);}//3.设置让自己成为自成一个新会话setsid(); //4. 每个进程都有自己的cwd,是否将当前进程cwd改为根目录if (changeCwd){chdir(path);}//5.已经变成守护进程了,不需要和键盘终端关联了(输入和输出)// 最佳方案:将0,1,2重定向到dev/null,避免代码中有cout样式的语句int fd = open(devNull, O_RDWR);dup2(fd, 0); //close 0号文件,然后让0号文件变成fd号文件dup2(fd, 1);dup2(fd, 2);
}
库里有现成的: