Linu系统编程---10(Linux的终端,线路规程,网络终端,进程组)
終端
輸入輸出設備的總稱
在 UNIX 系統中,用戶通過終端登錄系統后得到一個 Shell 進程,這個終端成為 Shell 進程的控制終端(Controlling Terminal),
進程中,控制終端是保存在 PCB 中的信息,而 fork 會復制 PCB 中的信息,因此由 Shell 進程啟動的其它 進程的控制終端也是這個終端。默認情況下(沒有重定向),每個進程的標準輸入、標準輸出和標準錯誤輸出都指 向控制終端,進程從標準輸入讀也就是讀用戶的鍵盤輸入,進程往標準輸出或標準錯誤輸出寫也就是輸出到顯示器 上。信號中還講過,在控制終端輸入一些特殊的控制鍵可以給前臺進程發信號,例如 Ctrl-C 表示 SIGINT,Ctrl-\表示 SIGQUIT。
終端的啟動流程
文件與 I/O 中講過,每個進程都可以通過一個特殊的設備文件/dev/tty 訪問它的控制終端。事實上每個終端設 備都對應一個不同的設備文件,/dev/tty 提供了一個通用的接口,一個進程要訪問它的控制終端既可以通過/dev/tty 也可以通過該終端設備所對應的設備文件來訪問。ttyname 函數可以由文件描述符查出對應的文件名,該文件描述 符必須指向一個終端設備而不能是任意文件。
Linux 系統啟動的終端順序:
init–>fork–>exec–>getty–> 用戶輸入帳號 -->login–> 輸入密碼 -->exec–>bash
線路規程
線路規程就 像一個過濾器, 對于某些特殊字符并不是讓它直接通過,而是做特殊處理,比如在鍵盤上按下 Ctrl-z,對應的字符并不會被用戶程序的 read 讀到,而是被線路規程截獲,解釋成 SIGTSTP 信號發給前臺進程,通常會使該進程停止。線路規程應該過濾哪些字符和做哪些特殊處理是可以配置的。
ttyname 函數
由文件描述符查出對應的文件名
char*ttyname(intfd); 成功:終端名;失敗:NULL,設置 errno 下面我們借助 ttyname 函數,通過實驗看一下各種不同的終端所對應的設備文件名。
網絡終端
虛擬終端或串口終端的數目是有限的,虛擬終端(字符控制終端)一般就是/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 函數的參數中都曾使用到。操作系統設計的進程組的概念,是為了簡 化對多個進程的管理。
性質
進程組操作相關函數
getpgrp 函數
獲取當前進程的進程組 ID pid_t getpgrp(void);
總是返回調用者的進程組 ID
getpgid 函數
獲取指定進程的進程組 ID pid_t getpgid(pid_t pid); 成功:0;失敗:-1,設置 errno
如果 pid=0,那么該函數作用和 getpgrp 一樣。
setpgid 函數
改變進程默認所屬的進程組。通常可用來加入一個現有的進程組或創建一個新進程組。
int setpgid(pid_t pid,pid_t pgid); 成功:0;失敗:-1,設置 errno 將參 1 對應的進程,加入參 2 對應的進程組中。
注意:
練習 :修改子進程的進程組 ID,查看進程對應的進程組 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));//獲取自己的進程組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("parent's 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; }結果:
總結
以上是生活随笔為你收集整理的Linu系统编程---10(Linux的终端,线路规程,网络终端,进程组)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 输卵管堵塞要什么办
- 下一篇: 江南百景图天书奇谭聚宝盆怎么获得