进程组
组长是多个进程的第一个,组长进程的标识是,其进程组ID等于其进程ID
前台进程&后台进程
前台进程:能获取键盘输入,即拥有键盘文件
后台进程:不能获取键盘输入,即没有键盘文件
前台进程只能有一个,当一个进程变成前台进程后,bash会自动变为后台进程,此时bash就无法进行命令行解释了。
命令行中前台进程要一直存在 ,不能没有
ctrl + c,可以终止前台进程
./myprocess & ,加了& ,就变成后台进程了
[cxq@iZwz9fjj2ssnshikw14avaZ lesson31]$ ll
total 36
-rw-rw-r-- 1 cxq cxq 90 Jul 15 22:41 Makefile
-rwxrwxr-x 1 cxq cxq 26440 Jul 15 15:31 myprocess
-rw-rw-r-- 1 cxq cxq 443 Jul 15 22:41 mysignal.cc
-rw-rw-r-- 1 cxq cxq 0 Jul 14 16:59 test.c
[cxq@iZwz9fjj2ssnshikw14avaZ lesson31]$ ./myprocess &
Linux中,一次登陆中,一个终端,一般会配上一个bash,每一个登陆,只允讲一个进程是前台进程,但是可以允许多个进程是后台进程
[cxq@iZwz9fjj2ssnshikw14avaZ lesson43]$ ./process >> log.txt &
[1] 27184
1: 后台任务号
27184是进程pid
查看后台任务
[cxq@iZwz9fjj2ssnshikw14avaZ lesson43]$ jobs
[1]+ Running ./process >> log.txt &
fg,将一个在后台运行的作业(job)调回到前台继续执行
[cxq@iZwz9fjj2ssnshikw14avaZ lesson43]$ jobs
[1]+ Running ./process >> log.txt &
[cxq@iZwz9fjj2ssnshikw14avaZ lesson43]$ fg 1
如果想要重新放回后台 ,ctrl + z
bg 命令用于将一个挂起(stopped)或暂停(suspended)的作业放入后台执行
[cxq@iZwz9fjj2ssnshikw14avaZ lesson43]$ jobs
[1] Running ./process >> log.txt &
[2]- Running ./process >> log.txt &
[3]+ Running ./process >> log1.txt &
[cxq@iZwz9fjj2ssnshikw14avaZ lesson43]$ fg 3
./process >> log1.txt
^Z
[3]+ Stopped ./process >> log1.txt
[cxq@iZwz9fjj2ssnshikw14avaZ lesson43]$ jobs
[1] Running ./process >> log.txt &
[2]- Running ./process >> log.txt &
[3]+ Stopped ./process >> log1.txt
[cxq@iZwz9fjj2ssnshikw14avaZ lesson43]$ bg 3
[3]+ ./process >> log1.txt &
守护进程
关闭xshell后 ,这几个进程TTY就没了 ,与终端无关了 ,PPID全部变成1 ,会话还是保留了关闭xshell前的会话ID,关闭xshell后 ,这几个进程的PID变化了,也就是说这几个进程会受到用户的登陆和注册的影响
守护进程化:不想受到任何用户登陆和注销的影响
守护进程 :自成进程组、自成会话的进程
守护进程的本质,就是孤儿进程
调用setsid创建新会话的目的,是让当前进程自成会话,与当前bash脱离关系
pid_t setsid(void);
调用setsid创建新会话时,要求调用进程不能是进程组组长,但是当我们在命令行上启动多个进程协同完成某种任务时,其中第一个被创建出来的进程就是组长进程,因此我们需要fork创建子进程,让子进程调用setsid创建新会话并继续执行后续代码,而父进程我们直接让其退出即可
//父进程退出 ,子进程创建新会话
if (fork() > 0)
exit(0);
setsid();
功能:网络版少数单词的翻译,涉及到守护进程
Daemon.hpp
#pragma once
#include <unistd.h>
#include <string>
#include <iostream>
#include <cstdlib>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
const std::string nullfile = "/dev/null";
void Daemon(const std::string &cwd = "") // 设置空串为缺省值
{
// 1. 忽略其他异常信号
signal(SIGCLD, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
signal(SIGSTOP, SIG_IGN);
// 父进程退出 ,子进程创建新会话
if (fork() > 0)
exit(0);
setsid();
// 3. 更改当前调用进程的工作目录
if (!cwd.empty()) // 不为空
{
chdir(cwd.c_str());
}
// 4. 标准输入,标准输出,标准错误重定向至/dev/null
int fd = open(nullfile.c_str(),O_RDWR );
if(fd > 0)
{
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
close(fd);
}
}
ls /proc/4686/fd -l, 系统会显示进程 ID 为 4686 的进程打开的所有文件描述符的详细信息
[cxq@iZwz9fjj2ssnshikw14avaZ lesson42]$ ps ajx | head -1 && ps ajx | grep Tcpserver
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
1 4686 4686 4686 ? -1 Ssl 1001 0:00 ./Tcpserver 8888
27777 11212 11211 27777 pts/1 11211 S+ 1001 0:00 grep --color=auto Tcpserver
[cxq@iZwz9fjj2ssnshikw14avaZ lesson42]$ ls /proc/4686/fd -l
total 0
lrwx------ 1 cxq cxq 64 Sep 16 12:36 0 -> /dev/null
lrwx------ 1 cxq cxq 64 Sep 16 12:36 1 -> /dev/null
lrwx------ 1 cxq cxq 64 Sep 16 12:36 2 -> /dev/null
lrwx------ 1 cxq cxq 64 Sep 16 12:36 3 -> socket:[5908905]
daemon
daemon,创建守护进程
int daemon(int nochdir, int noclose);
- 如果参数nochdir为0,则将守护进程的工作目录该为根目录,否则不做处理。
- 如果参数noclose为0,则将守护进程的标准输入、标准输出以及标准错误重定向到/dev/null,否则不做处理。