Linux下的进程(四):进程关系 - HeavyYuan/A-CD-Record-Management-System GitHub Wiki
systemd-logind
|
fork
|
\|/
systemd-logind
|
exec
|
\|/
agetty 打开终端设备,读取用户输入账户信息(即登录界面是由agetty提供的)
|
exec 这里没有fork,直接是吧agetty的进程映像**替换**成login的映像
|
\|/
login 身份验证
|
fork
|
\|/
shell(bash)
系统启动后,默认只产生一个agetty进程(和tty1绑定),此时不要在本地登录系统,通过ssh登录后,ps -ef | grep agetty
可以看到这个agetty进程
alt + F2-F7可以启动其他的agetty进程
1个 或 多个进程,形成进程组;一个 或 多个进程组,形成会话
进程组有唯一的进程组ID == 该组组长进程ID
会话有唯一的会话ID == 会话首进程的进程ID
创建会话的进程是该会话的会话首进程(session leader)
一个会话可以有一个控制终端(controlling terminal)(常常指tty或pts)
会话首进程(一般是bash)是控制进程(controlling process),其建立了进程和控制终端的连接(bash的/proc/pid/fd下的文件描述符默认指向终端设备)
会话中的进程组分成(有且只有)一个前台进程组(foreground process group)和一个后台进程组(background process group)
前后台进程组ID不是进程的属性,而是终端的属性,即是终端来判断谁是前~,谁是后~
ps o tpgid,comm
查看当前控制终端的进程id(tpgid),即前台进程,其余的都是后台进程
作业控制允许在一个终端上启动多个作业(进程组),它控制哪一个作业可以访问终端(前台进程组),以及哪些作业在后台运行。
作业控制常见手段:
后台运行命令:& 挂起前台进程:CTRL + Z 进程恢复到前台运行:fg %jobnumber
只有前台作业接受终端输入,终端输出可以通过stty tostop
来阻止后台作业输出到终端。
ps o tpgid,comm
查看当前控制终端的进程id(tpgid),即前台进程,其余的都是后台进程
以下程序,当前子进程中有read操作,当子进程变成后台作业之后,读取报错。
//from apue.3e(orphan3.c)
#include "apue.h"
#include <errno.h>
static void
sig_hup(int signo)
{
printf("SIGHUP received, pid = %ld\n", (long)getpid());
}
static void
pr_ids(char *name)
{
printf("%s: pid = %ld, ppid = %ld, pgrp = %ld, tpgrp = %ld\n",
name, (long)getpid(), (long)getppid(), (long)getpgrp(),
(long)tcgetpgrp(STDIN_FILENO));
fflush(stdout);
}
int
main(void)
{
char c;
pid_t pid;
pr_ids("parent");
if ((pid = fork()) < 0) {
err_sys("fork error");
} else if (pid > 0) { /* parent */
sleep(5); /* sleep to let child stop itself */
} else { /* child */
pr_ids("child");
signal(SIGHUP, sig_hup); /* establish signal handler */
kill(getpid(), SIGTSTP); /* stop ourself */
pr_ids("child"); /* prints only if we're continued */
if (read(STDIN_FILENO, &c, 1) != 1)。//读取报错
printf("read error %d on controlling TTY\n", errno);
}
exit(0);
}
ps axo pid,ppid,pgid,sid,tpgid,comm
输出:
进程pid,父进程pid,进程组id,会话组id,当前控制tty的进程id,进程名
当前控制tty的进程id:当前控制终端的进程id,进入bash后,该会话的前台进程组id就是tpgid,如果在该bash下运行一个vim,
可以看到该会话的tpgid就是vim进程id
父进程已经终止的进程称为孤儿进程(orphan process),这种进程有systemd“收养”
孤儿进程组(orphaned process group):该组中每个成员的父进程都是该组的成员,或者不在该组所在的会话