ps命令一般用来显示终端信息和进程信息,运行命令ps -eo pid,comm,cmd可以输出所有进程的信息,e代表所有进程,后面三个参数是需要输出的信息。
第一列PID是一个整数,每一个进程都有一个唯一的PID来代表自己的身份,进程也可以根据PID来识别其他的进程。第二列COMMAND是这个进程的简称。第三列CMD是进程所对应的程序以及运行时所带的参数。 
PID为1的进程是systemd,运行/sbin/init后出现。如果运行ps aux命令,可以看到第一个进程就是init。
计算机启动时,只有一个根进程init,可以通过命令pstree查看。Linux创建新进程用的是fork机制,所有进程都是从init进程fork而来,也就是说Linux进程是个树形结构。目前Systemd取代了initd,成为系统的第一个进程(PID=1),其他进程都是它的子进程。根据 Linux 惯例,字母d是守护进程(daemon)的缩写。 Systemd 这个名字的含义,就是它要守护整个系统。
fork复制老进程产生了新进程,它在内存中开辟一段空间供子进程使用,并将老的进程空间中的内容复制到新的空间中,此后两个进程同时运行。老进程被称为父进程,新进程为子进程,Linux提供了ppid表示某进程的父进程ID。fork函数返回类型为pid_t,实质为unsigned int,而且有两次返回,一次返回子进程ID给父进程,一次返回0给子进程。
父子进程的相同之处:用户ID,宿主工作目录,工作目录,代码段、栈堆、环境变量等等。
父子进程的不同之处:进程PID,PPID,fork返回值,进程运行时间,定时器。
父子进程间遵循**读时共享写时复制**的原则,这是为了节省内存。
父子进程共享:文件描述符,mmap的映射区。通常在调用fork函数之后,程序会设计一个if结构。当PID等于0时,说明该进程为子进程,那么让它执行某些指令,比如说使用exec库函数读取另一个程序文件,并在当前的进程空间执行 (这实际上是fork的一大目的: 为某一程序创建进程);而当PID为一个正整数时,说明为父进程,则执行另外一些指令。由此,就可以在子进程建立之后,让它执行与父进程不同的功能。fork之后先执行父进程还是子进程是不确定的,取决于内核的调度算法。
进程组
每个进程都属于一个进程组,进程组包含多个进程,其中一个是领导进程,领导进程的PID就是进程组的PID。
运行命令ps -o pid,pgid,ppid,comm | cat
PID PGID PPID COMMAND
17763 17763 17751 bash
18534 18534 17763 ps
18535 18534 17763 catPID为进程自身的ID,PGID为进程所在的进程组的ID,PPID为进程的父进程ID。从上面的结果,我们可以推测出如下关系: 
ps和cat都是bash的子进程。进程组的领导进程的PID成为进程组ID。领导进程可以先终结。此时进程组依然存在,并持有相同的PGID,直到进程组中最后一个进程终结。
pid,ppid,pgid信息都保存在Linux内核区的task_struct结构体中,内核可以通过查看自己空间中的各个进程的附加信息就能知道进程的概况,而不用进入到进程自身的空间。
getpgrp函数可获取当前进程的进程组ID。getpgid函数可获取指定进程的进程组ID。setpgid函数可改变进程默认的进程组,可加入另一个进程组或创建进程组。