Linu系统编程---10(Linux的终端,线路规程,网络终端,进程组)
終端
輸入輸出設(shè)備的總稱
在 UNIX 系統(tǒng)中,用戶通過終端登錄系統(tǒng)后得到一個(gè) Shell 進(jìn)程,這個(gè)終端成為 Shell 進(jìn)程的控制終端(Controlling Terminal),
進(jìn)程中,控制終端是保存在 PCB 中的信息,而 fork 會(huì)復(fù)制 PCB 中的信息,因此由 Shell 進(jìn)程啟動(dòng)的其它 進(jìn)程的控制終端也是這個(gè)終端。默認(rèn)情況下(沒有重定向),每個(gè)進(jìn)程的標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸出都指 向控制終端,進(jìn)程從標(biāo)準(zhǔn)輸入讀也就是讀用戶的鍵盤輸入,進(jìn)程往標(biāo)準(zhǔn)輸出或標(biāo)準(zhǔn)錯(cuò)誤輸出寫也就是輸出到顯示器 上。信號(hào)中還講過,在控制終端輸入一些特殊的控制鍵可以給前臺(tái)進(jìn)程發(fā)信號(hào),例如 Ctrl-C 表示 SIGINT,Ctrl-\表示 SIGQUIT。
終端的啟動(dòng)流程
文件與 I/O 中講過,每個(gè)進(jìn)程都可以通過一個(gè)特殊的設(shè)備文件/dev/tty 訪問它的控制終端。事實(shí)上每個(gè)終端設(shè) 備都對(duì)應(yīng)一個(gè)不同的設(shè)備文件,/dev/tty 提供了一個(gè)通用的接口,一個(gè)進(jìn)程要訪問它的控制終端既可以通過/dev/tty 也可以通過該終端設(shè)備所對(duì)應(yīng)的設(shè)備文件來訪問。ttyname 函數(shù)可以由文件描述符查出對(duì)應(yīng)的文件名,該文件描述 符必須指向一個(gè)終端設(shè)備而不能是任意文件。
Linux 系統(tǒng)啟動(dòng)的終端順序:
init–>fork–>exec–>getty–> 用戶輸入帳號(hào) -->login–> 輸入密碼 -->exec–>bash
線路規(guī)程
線路規(guī)程就 像一個(gè)過濾器, 對(duì)于某些特殊字符并不是讓它直接通過,而是做特殊處理,比如在鍵盤上按下 Ctrl-z,對(duì)應(yīng)的字符并不會(huì)被用戶程序的 read 讀到,而是被線路規(guī)程截獲,解釋成 SIGTSTP 信號(hào)發(fā)給前臺(tái)進(jìn)程,通常會(huì)使該進(jìn)程停止。線路規(guī)程應(yīng)該過濾哪些字符和做哪些特殊處理是可以配置的。
ttyname 函數(shù)
由文件描述符查出對(duì)應(yīng)的文件名
char*ttyname(intfd); 成功:終端名;失敗:NULL,設(shè)置 errno 下面我們借助 ttyname 函數(shù),通過實(shí)驗(yàn)看一下各種不同的終端所對(duì)應(yīng)的設(shè)備文件名。
網(wǎng)絡(luò)終端
虛擬終端或串口終端的數(shù)目是有限的,虛擬終端(字符控制終端)一般就是/dev/tty1~/dev/tty6 六個(gè),
串口終端的數(shù) 目也不超過串口的數(shù)目。然而網(wǎng)絡(luò)終端或圖形終端窗口的數(shù)目卻是不受限制的,這是通過偽終端(PseudoTTY) 實(shí)現(xiàn)的**。一套偽終端由一個(gè)主設(shè)備(PTYMaster)和一個(gè)從設(shè)備(PTYSlave)組成**。
主設(shè)備在概念上相當(dāng)于鍵盤和 顯示器,只不過它不是真正的硬件而是一個(gè)內(nèi)核模塊,操作它的也不是用戶而是另外一個(gè)進(jìn)程。
從設(shè)備和上面介紹 的/dev/tty1 這樣的終端設(shè)備模塊類似,只不過它的底層驅(qū)動(dòng)程序不是訪問硬件而是訪問主設(shè)備。
網(wǎng)絡(luò)終端或圖形終 端窗口的 Shell 進(jìn)程以及它啟動(dòng)的其它進(jìn)程都會(huì)認(rèn)為自己的控制終端是偽終端從設(shè)備,例如/dev/pts/0、/dev/pts/1 等。下面以 telnet 為例說明網(wǎng)絡(luò)登錄和使用偽終端的過程。
TCP/IP 協(xié)議棧:
在數(shù)據(jù)包上添加報(bào)頭。 如果telnet客戶端和服務(wù)器之間的網(wǎng)絡(luò)延遲較大, 我們會(huì)觀察到按下一個(gè)鍵之后要過幾秒鐘才能回顯到屏幕上。 這說明我們每按一個(gè)鍵 telnet 客戶端都會(huì)立刻把該字符發(fā)送給服務(wù)器,然后這個(gè)字符經(jīng)過偽終端主設(shè)備和從設(shè)備之后被 Shell 進(jìn)程讀取,同時(shí)回顯到偽終端從設(shè)備,回顯的字符再經(jīng)過偽終端主設(shè)備、 telnetd 服務(wù)器和網(wǎng)絡(luò)發(fā)回給 telnet 客戶端,顯示給用戶看。其實(shí)每按一個(gè)鍵都要在網(wǎng)絡(luò)上走個(gè)來回!
進(jìn)程組
概念
進(jìn)程組,也稱之為作業(yè)。BSD 于 1980 年前后向 Unix 中增加的一個(gè)新特性。代表一個(gè)或多個(gè)進(jìn)程的集合。每個(gè) 進(jìn)程都屬于一個(gè)進(jìn)程組。在 waitpid 函數(shù)和 kill 函數(shù)的參數(shù)中都曾使用到。操作系統(tǒng)設(shè)計(jì)的進(jìn)程組的概念,是為了簡 化對(duì)多個(gè)進(jìn)程的管理。
性質(zhì)
進(jìn)程組操作相關(guān)函數(shù)
getpgrp 函數(shù)
獲取當(dāng)前進(jìn)程的進(jìn)程組 ID pid_t getpgrp(void);
總是返回調(diào)用者的進(jìn)程組 ID
getpgid 函數(shù)
獲取指定進(jìn)程的進(jìn)程組 ID pid_t getpgid(pid_t pid); 成功:0;失敗:-1,設(shè)置 errno
如果 pid=0,那么該函數(shù)作用和 getpgrp 一樣。
setpgid 函數(shù)
改變進(jìn)程默認(rèn)所屬的進(jìn)程組。通常可用來加入一個(gè)現(xiàn)有的進(jìn)程組或創(chuàng)建一個(gè)新進(jìn)程組。
int setpgid(pid_t pid,pid_t pgid); 成功:0;失敗:-1,設(shè)置 errno 將參 1 對(duì)應(yīng)的進(jìn)程,加入?yún)?2 對(duì)應(yīng)的進(jìn)程組中。
注意:
練習(xí) :修改子進(jìn)程的進(jìn)程組 ID,查看進(jìn)程對(duì)應(yīng)的進(jìn)程組 ID
#include<stdio.h> #include<stdlib.h> #include<unistd.h>int 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));//獲取自己的進(jìn)程組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); //讓子進(jìn)程自立門戶,成為進(jìn)程組組長,以它的pid為進(jìn)程組idsleep(13);printf("\n");printf("parent PID == %d\n",getpid());printf("parent's parent process PID == %d\n",getppid());printf("parent Group ID == %d\n",getpgid(0));sleep(5);setpgid(getpid(),getppid());//改變父進(jìn)程的組id為父進(jìn)程的父進(jìn)程printf("\n------Group ID of parent is changeto %d\n",getpgid(0));while(1);} return 0; }結(jié)果:
總結(jié)
以上是生活随笔為你收集整理的Linu系统编程---10(Linux的终端,线路规程,网络终端,进程组)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 输卵管堵塞要什么办
- 下一篇: 江南百景图天书奇谭聚宝盆怎么获得