相关函数列表
//返回调用进程的进程组ID 系统管理者创建/etc/ttys文件,之后init进程读取这个文件,然后fork新进程执行exec调用getty程序 getty对终端设备调用open函数,以读写方式将终端打开,一旦设备打开,则文件描述符就被设置到该设备,然后getty输出“login”之类的信息。getty会根据波特率适当的更改终端的速度。 当用户输入用户名后,getty工作就完成了,然后它调用login程序 execle("/bin/login", "login" "-p", username, (char*)0, envp); 最初的init进程有超级用户权限,所以它fork后的进程都有超级用户权限 login能处理多项工作,得到用户名调用getpwnam取得相应的用户口令,然后调用getpass提示"password",用户输入口令后,调用crypt将用户口令加密,并与阴影文件的pw_passwd字段比较,如果出错则login调用exit表示登陆失败,父进程init了解到子进程情况后再次调用fork又执行getty,重复上述过程 如果用户登陆正常login就将完成如下工作: 1)将当前工作目录更改为用户的起始目录(chdir) 2)调用chown更改该终端的所有权,使登陆用户成为它的所有者 3)将对该终端设备的访问权限改变为“用户读和写” 4)调用setgid以及initgroups设置进程的组ID 5)用login得到所有信息初始化环境:起始目录(HOME),shell(SHELL),用户名(USER和LOGNAME)以及一个 系统默认路径(PATH) 6)login进程更改为登陆用户的用户ID(setuid)并调用该用户的登陆shell,其方式类似于 execl("/bin/sh", "-sh", (char*)0); init进程调用一个shell,使其执行shell脚本/etc/rc,由此shell脚本启动一个守护进程inetd。一旦shell脚本终止,inetd的父进程就变成init。inetd等待TCP连接达到主机,然后执行一次fork,生成子进程exec执行适当的程序。 当telnet请求达到后,inetd会fork一个进程,然后执行telnetd程序(exec调用),之后分成两个进程,父进程继续处理连接的通讯,子进程执行login程序,父进程和子进程通过伪终端相连接。 执行过程: 1.init调用fork和exec启动inetd 2.inetd接收到客户端的telnet连接,然后fork新进程 3.inetd继续接受客户来的连接,新进程调用exec启动telnetd处理用户逻辑 进程组是一个或多个进程的集合,会话是一个或多个进程组的集合 比如proc1 | proc2 & | proc3 | proc4 | proc5 会话和进程组还有一些其他特性 1.一个会话可以有一个控制终端(controlling terminal),这通常是终端设备(在终端登录)或伪终端设备(网络) 2..建立与控制终端连接的会话首进程被称为控制进程(controlling process) 3.一个会话中的几个进程组可被分成一个前台进程组(foreground process group)以及一个或多个后台进程 组(background process group) 4.如果一个会话有一个控制终端,则它有一个前台进程组,其他进程组为后台进程组 5.无论何时键入终端的中断键,都会将终端信号发送至前台进程组的所有进程 6.如果终端接口检测到调制解调器(或网络)已断开连接,则将挂断信号发送至控制进程(会话首进程) 允许在一个终端上启动多个作业(进程组),它控制一个作业可以访问该终端以及哪些作业在后台运行。要求以下三种形式的支持: 1.支持作业控制的shell 2.内核中的终端驱动程序必须支持作业控制 3.内核必须提供对某些作业控制信号的支持 //这里启动了两个作业
#include
pid_t getpgrp(void);
pid_t getpgid(pid_t pid);
//getpgid(0) 等于 getpgrp()
//创建一个新会话
#include
pid_t setsid(void);
pid_t getsid(get_t pid); //返回会话首进程的进程组ID
//对于setsid()函数,如果调用此函数的进程不是一个进程组的组长,则此函数创建一个新会话
//1.该进程变成新会话的会话首进程(session leader会话首进程是创建该会话的进程),此时,该进程
// 是新会话中唯一进程
//2.该进程成为一个新进程组的组长进程。新进程组ID是该调用进程的进程ID
//3.该进程没有控制终端,如果在调用setsid之前该进程有一个控制终端,那么这种联系也被切断
//根据FD获取哪个进程组是前台进程组
#include
pid_t tcgetpgrp(int fd);
int tcsetpgrp(int fd, pid_t pgrpid);
//给出控制TTY的文件描述符,下面函数可以获得会话首进程的进程组ID
#include
pid_t tcgetsid(int fd);
终端登录
网络登陆
会话
作业控制
pr *.c | lpr &
make all &
//在后台运行,之后又将作业1号变为前台运行
cat > temp.foo &
fg %1
stty tostop //禁止作业输出至控制终端
对于前台,后台作业以及终端驱动程序的作业控制功能总结