相关函数列表
//返回调用进程的进程组ID #include <unistd.h> pid_t getpgrp(void); pid_t getpgid(pid_t pid); //getpgid(0) 等于 getpgrp() //创建一个新会话 #include <unistd.h> pid_t setsid(void); pid_t getsid(get_t pid); //返回会话首进程的进程组ID //对于setsid()函数,如果调用此函数的进程不是一个进程组的组长,则此函数创建一个新会话 //1.该进程变成新会话的会话首进程(session leader会话首进程是创建该会话的进程),此时,该进程 // 是新会话中唯一进程 //2.该进程成为一个新进程组的组长进程。新进程组ID是该调用进程的进程ID //3.该进程没有控制终端,如果在调用setsid之前该进程有一个控制终端,那么这种联系也被切断 //根据FD获取哪个进程组是前台进程组 #include <unistd.h> pid_t tcgetpgrp(int fd); int tcsetpgrp(int fd, pid_t pgrpid); //给出控制TTY的文件描述符,下面函数可以获得会话首进程的进程组ID #include <unistd.h> pid_t tcgetsid(int fd);
终端登录
系统管理者创建/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.内核必须提供对某些作业控制信号的支持
//这里启动了两个作业 pr *.c | lpr & make all & //在后台运行,之后又将作业1号变为前台运行 cat > temp.foo & fg %1 stty tostop //禁止作业输出至控制终端对于前台,后台作业以及终端驱动程序的作业控制功能总结