?
?
相關函數列表
//返回調用進程的進程組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 //禁止作業輸出至控制終端?對于前臺,后臺作業以及終端驅動程序的作業控制功能總結
?
?
shell執行程序
//執行下面這段shell ps -o pid,ppid,pgid,sid,tpgid,comm | cat | cat | tail | more | head //結果 PID PPID PGID SID TPGID COMMAND 26383 26381 26383 26383 26514 bash 26456 26383 26450 26383 26514 more 26514 26383 26514 26383 26514 ps 26515 26383 26514 26383 26514 cat 26516 26383 26514 26383 26514 cat 26517 26383 26514 26383 26514 tail 26518 26383 26514 26383 26514 more 26519 26383 26514 26383 26514 head
?從結果中可以看到,所有的命令都父進程ID都是bash,也就是bash去啟動了那些命令
而ps,cat,cat,tail,more,head這些命令是在一個進程組中的。同時上面所有的進程都是在一個會話中
Bourne shell執行管道ps | cat1 | cat2時的進程
這里執行的sh后,又會fork一個新進程,然后這個新的sh進程再去fork一些子進程,fork的這些子進程都是執行
sh命令,這些sh命令又調用exec函數執行不同的shell命令,比如ps,cat這樣的
管道中最后一個shell命令是由最初的sh(PID為202)調用exec執行的
當然這里不同的sh執行會有不同的效果,而且創建的進程順序也會不同
linux上的bash shell對于所有的執行的管道命令都是bash的子進程?
?
通過pstree命令執行
ps -o pid,ppid,gid,sid,comm | cat | more | head | pstree //結果 init-+-bash |-6*[mingetty] |-sshd---sshd-+-bash | `-bash-+-cat | |-head | |-more | |-ps | `-pstree `-udevd
可以看到init進程for了sshd(也就是終端),然后sshd又fork了bash,
bash調用exec再fork了cat,head,more,ps等命令,生成相應的進程
?
?
?
孤兒進程組
一個其父進程已經終止的進程稱為孤兒進程(orphan process),這種進程由init進程收養,而整個進程組也有可能成為孤兒。
POSIX.1將孤兒進程組(orphaned process group)定義為:
該組中每個成員的父進程要么是該組的一個成員,要么不是該組所屬會話的成員。
對孤兒進程組的另一種描述可以使:
一個進程組不是孤兒進程組的條件是---該組中有一個進程,其父進程在屬于同一會話的另一個組中。如果進程組
不是孤兒進程組,name在屬于同一會話另一個組中的父進程就有機會重新啟動該組中停止的進程。在這里,進程組中每一個進程的父進程都屬于另一個會話。所以此進程組是孤兒進程組。
?
?
?
FreeBSD實現
會話和進程組的FreeBSD實現
1)s_count是該會話中的進程組數。當此計數器減至0時,則可釋放此結構
2)s_leader是指向會話首進程proc結構體的指針
3)s_ttyvp是指向控制終端vnode結構的指針
4)s_ttyp是指向控制終端tty結構的指針
5)s_sid是會話id
?
tty結構體
1)t_session指向將此終端作為控制終端的session結構(注意,tty結構指向session結構,session結構也指向
? ?tty)。終端在市區載波信號時使用此指針將掛起信息發送給會話首進程
2)t_pgrp是指向前臺進程組的pgrp結構。終端驅動程序用此字段將信號發送給前臺進程組。
3)t_termios是包含所有這些特殊字符和與該終端有關信息(如波特率,回顯打開或關閉)的結構
4)t_winsize是包含終端窗口當前大小的winsize型結構。當終端窗口大小改變時,信號SIGWINCH被發送至前臺
? ?進程組。
?
pgrp結構體(包含一個特定進程組的信息)
1)pg_id是進程組ID
2)pg_session指向此進程組所屬會話的session結構
3)pg_members是指向此進程組proc結構表的指針,該proc結構代表進程組的成員
?
proc結構體
1)p_pid包含進程ID
2)p_pptr是指向父進程proc結構的指針
3)p_pglist是一個結構,其中包含兩個指針,分別指向進程組中上一個和下一個進程
最后還有一個vnode結構,在打開控制終端設備時分配此結構體,進程對/dev/tty的所有訪問都通過vnode。
?
?
?
?
?
?
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
