网站建设需要会什么软件有哪些,网站设计的内容以及步骤,vi设计案例分析,国内免费云服务器推荐终端
输入输出设备的总称 在 UNIX 系统中#xff0c;用户通过终端登录系统后得到一个 Shell 进程#xff0c;这个终端成为 Shell 进程的控制终端#xff08;Controlling Terminal#xff09;#xff0c; 进程中#xff0c;控制终端是保存在 PCB 中的信息#xff0c;而 …终端
输入输出设备的总称 在 UNIX 系统中用户通过终端登录系统后得到一个 Shell 进程这个终端成为 Shell 进程的控制终端Controlling Terminal 进程中控制终端是保存在 PCB 中的信息而 fork 会复制 PCB 中的信息因此由 Shell 进程启动的其它 进程的控制终端也是这个终端。默认情况下没有重定向每个进程的标准输入、标准输出和标准错误输出都指 向控制终端进程从标准输入读也就是读用户的键盘输入进程往标准输出或标准错误输出写也就是输出到显示器 上。信号中还讲过在控制终端输入一些特殊的控制键可以给前台进程发信号例如 Ctrl-C 表示 SIGINTCtrl-\表示 SIGQUIT。
AltCtrlF1、F2、F3、F4、F5、F6 字符终端 。pts(pseudoterminalslave) 指伪终端。AltF7 图形终端SSH、Telnet… 网络终端
终端的启动流程
文件与 I/O 中讲过每个进程都可以通过一个特殊的设备文件/dev/tty 访问它的控制终端。事实上每个终端设 备都对应一个不同的设备文件/dev/tty 提供了一个通用的接口一个进程要访问它的控制终端既可以通过/dev/tty 也可以通过该终端设备所对应的设备文件来访问。ttyname 函数可以由文件描述符查出对应的文件名该文件描述 符必须指向一个终端设备而不能是任意文件。
Linux 系统启动的终端顺序
init–fork–exec–getty– 用户输入帐号 --login– 输入密码 --exec–bash
线路规程
线路规程就 像一个过滤器 对于某些特殊字符并不是让它直接通过而是做特殊处理比如在键盘上按下 Ctrl-z对应的字符并不会被用户程序的 read 读到而是被线路规程截获解释成 SIGTSTP 信号发给前台进程通常会使该进程停止。线路规程应该过滤哪些字符和做哪些特殊处理是可以配置的。
linedisciline: 线路规程用来过滤键盘输入的内容。ttyname 函数
由文件描述符查出对应的文件名 char*ttyname(intfd); 成功终端名失败NULL设置 errno 下面我们借助 ttyname 函数通过实验看一下各种不同的终端所对应的设备文件名。
#includeunistd.h#includestdio.hintmain(void){printf(fd0:%s\n,ttyname(0));printf(fd1:%s\n,ttyname(1)); printf(fd2:%s\n,ttyname(2));return0;} 网络终端
虚拟终端或串口终端的数目是有限的虚拟终端(字符控制终端)一般就是/dev/tty1∼/dev/tty6 六个 串口终端的数 目也不超过串口的数目。然而网络终端或图形终端窗口的数目却是不受限制的这是通过伪终端PseudoTTY 实现的**。一套伪终端由一个主设备PTYMaster和一个从设备PTYSlave组成**。 主设备在概念上相当于键盘和 显示器只不过它不是真正的硬件而是一个内核模块操作它的也不是用户而是另外一个进程。 从设备和上面介绍 的/dev/tty1 这样的终端设备模块类似只不过它的底层驱动程序不是访问硬件而是访问主设备。 网络终端或图形终 端窗口的 Shell 进程以及它启动的其它进程都会认为自己的控制终端是伪终端从设备例如/dev/pts/0、/dev/pts/1 等。下面以 telnet 为例说明网络登录和使用伪终端的过程。
TCP/IP 协议栈
在数据包上添加报头。 如果telnet客户端和服务器之间的网络延迟较大 我们会观察到按下一个键之后要过几秒钟才能回显到屏幕上。 这说明我们每按一个键 telnet 客户端都会立刻把该字符发送给服务器然后这个字符经过伪终端主设备和从设备之后被 Shell 进程读取同时回显到伪终端从设备回显的字符再经过伪终端主设备、 telnetd 服务器和网络发回给 telnet 客户端显示给用户看。其实每按一个键都要在网络上走个来回
进程组
概念
进程组也称之为作业。BSD 于 1980 年前后向 Unix 中增加的一个新特性。代表一个或多个进程的集合。每个 进程都属于一个进程组。在 waitpid 函数和 kill 函数的参数中都曾使用到。操作系统设计的进程组的概念是为了简 化对多个进程的管理。
性质
当父进程创建子进程的时候默认子进程与父进程属于同一进程组。进程组 ID第一个进程 ID(组长进程)。 所以组长进程标识其进程组 ID其进程 ID可以使用 kill-SIGKILL9-进程组 ID(负的)来将整个进程组内的进程全部杀死。组长进程可以创建一个进程组创建该进程组中的进程然后终止。只要进程组中有一个进程存在进程组就 存在与组长进程是否终止无关。进程组生存期进程组创建到最后一个进程离开(终止或转移到另一个进程组)。一个进程可以为自己或子进程设置进程组 ID
进程组操作相关函数
getpgrp 函数
获取当前进程的进程组 ID pid_t getpgrp(void); 总是返回调用者的进程组 ID
getpgid 函数
获取指定进程的进程组 ID pid_t getpgid(pid_t pid); 成功0失败-1设置 errno 如果 pid0那么该函数作用和 getpgrp 一样。
setpgid 函数
改变进程默认所属的进程组。通常可用来加入一个现有的进程组或创建一个新进程组。 int setpgid(pid_t pid,pid_t pgid); 成功0失败-1设置 errno 将参 1 对应的进程加入参 2 对应的进程组中。 注意
如改变子进程为新的组应 fork 后exec 前。权级问题。非 root 进程只能改变自己创建的子进程或有权限操作的进
练习 修改子进程的进程组 ID查看进程对应的进程组 ID
#includestdio.h
#includestdlib.h
#includeunistd.hint main(void)
{pid_t pid;if((pid fork()) 0 ){perror(fork);exit(1);}else if(pid 0){ printf(child PID %d\n,getpid());printf(child Group ID %d\n,getpgid(0));//获取自己的进程组ID //返回组
id //printf(child Group ID %d\n,getpgrp());//返回组idsleep(7);printf(------Group ID of child is changed to %d\n,getpgid(0));}else if(pid 0){ sleep(1);setpgid(pid,pid); //让子进程自立门户成为进程组组长以它的pid为进程组idsleep(13);printf(\n);printf(parent PID %d\n,getpid());printf(parents parent process PID %d\n,getppid());printf(parent Group ID %d\n,getpgid(0));sleep(5);setpgid(getpid(),getppid());//改变父进程的组id为父进程的父进程printf(\n------Group ID of parent is changeto %d\n,getpgid(0));while(1);} return 0;
}结果