?
?
相關(guān)函數(shù)列表
//返回調(diào)用進(jìn)程的進(jìn)程組ID #include <unistd.h> pid_t getpgrp(void); pid_t getpgid(pid_t pid); //getpgid(0) 等于 getpgrp() //創(chuàng)建一個(gè)新會(huì)話 #include <unistd.h> pid_t setsid(void); pid_t getsid(get_t pid); //返回會(huì)話首進(jìn)程的進(jìn)程組ID //對(duì)于setsid()函數(shù),如果調(diào)用此函數(shù)的進(jìn)程不是一個(gè)進(jìn)程組的組長,則此函數(shù)創(chuàng)建一個(gè)新會(huì)話 //1.該進(jìn)程變成新會(huì)話的會(huì)話首進(jìn)程(session leader會(huì)話首進(jìn)程是創(chuàng)建該會(huì)話的進(jìn)程),此時(shí),該進(jìn)程 // 是新會(huì)話中唯一進(jìn)程 //2.該進(jìn)程成為一個(gè)新進(jìn)程組的組長進(jìn)程。新進(jìn)程組ID是該調(diào)用進(jìn)程的進(jìn)程ID //3.該進(jìn)程沒有控制終端,如果在調(diào)用setsid之前該進(jìn)程有一個(gè)控制終端,那么這種聯(lián)系也被切斷 //根據(jù)FD獲取哪個(gè)進(jìn)程組是前臺(tái)進(jìn)程組 #include <unistd.h> pid_t tcgetpgrp(int fd); int tcsetpgrp(int fd, pid_t pgrpid); //給出控制TTY的文件描述符,下面函數(shù)可以獲得會(huì)話首進(jìn)程的進(jìn)程組ID #include <unistd.h> pid_t tcgetsid(int fd);
?
?
?
終端登錄
系統(tǒng)管理者創(chuàng)建/etc/ttys文件,之后init進(jìn)程讀取這個(gè)文件,然后fork新進(jìn)程執(zhí)行exec調(diào)用getty程序
getty對(duì)終端設(shè)備調(diào)用open函數(shù),以讀寫方式將終端打開,一旦設(shè)備打開,則文件描述符就被設(shè)置到該設(shè)備,然后getty輸出“l(fā)ogin”之類的信息。getty會(huì)根據(jù)波特率適當(dāng)?shù)母慕K端的速度。
當(dāng)用戶輸入用戶名后,getty工作就完成了,然后它調(diào)用login程序
execle("/bin/login", "login" "-p", username, (char*)0, envp);
最初的init進(jìn)程有超級(jí)用戶權(quán)限,所以它fork后的進(jìn)程都有超級(jí)用戶權(quán)限?
login能處理多項(xiàng)工作,得到用戶名調(diào)用getpwnam取得相應(yīng)的用戶口令,然后調(diào)用getpass提示"password",用戶輸入口令后,調(diào)用crypt將用戶口令加密,并與陰影文件的pw_passwd字段比較,如果出錯(cuò)則login調(diào)用exit表示登陸失敗,父進(jìn)程init了解到子進(jìn)程情況后再次調(diào)用fork又執(zhí)行g(shù)etty,重復(fù)上述過程
如果用戶登陸正常login就將完成如下工作:
1)將當(dāng)前工作目錄更改為用戶的起始目錄(chdir)
2)調(diào)用chown更改該終端的所有權(quán),使登陸用戶成為它的所有者
3)將對(duì)該終端設(shè)備的訪問權(quán)限改變?yōu)椤坝脩糇x和寫”
4)調(diào)用setgid以及initgroups設(shè)置進(jìn)程的組ID
5)用login得到所有信息初始化環(huán)境:起始目錄(HOME),shell(SHELL),用戶名(USER和LOGNAME)以及一個(gè)
? ?系統(tǒng)默認(rèn)路徑(PATH)
6)login進(jìn)程更改為登陸用戶的用戶ID(setuid)并調(diào)用該用戶的登陸shell,其方式類似于
execl("/bin/sh", "-sh", (char*)0);
?
?
網(wǎng)絡(luò)登陸
init進(jìn)程調(diào)用一個(gè)shell,使其執(zhí)行shell腳本/etc/rc,由此shell腳本啟動(dòng)一個(gè)守護(hù)進(jìn)程inetd。一旦shell腳本終止,inetd的父進(jìn)程就變成init。inetd等待TCP連接達(dá)到主機(jī),然后執(zhí)行一次fork,生成子進(jìn)程exec執(zhí)行適當(dāng)?shù)某绦颉?
當(dāng)telnet請(qǐng)求達(dá)到后,inetd會(huì)fork一個(gè)進(jìn)程,然后執(zhí)行telnetd程序(exec調(diào)用),之后分成兩個(gè)進(jìn)程,父進(jìn)程繼續(xù)處理連接的通訊,子進(jìn)程執(zhí)行l(wèi)ogin程序,父進(jìn)程和子進(jìn)程通過偽終端相連接。
執(zhí)行過程:
1.init調(diào)用fork和exec啟動(dòng)inetd
2.inetd接收到客戶端的telnet連接,然后fork新進(jìn)程
3.inetd繼續(xù)接受客戶來的連接,新進(jìn)程調(diào)用exec啟動(dòng)telnetd處理用戶邏輯
?
會(huì)話
進(jìn)程組是一個(gè)或多個(gè)進(jìn)程的集合,會(huì)話是一個(gè)或多個(gè)進(jìn)程組的集合
比如proc1 | proc2 & | proc3 | proc4 | proc5
?
會(huì)話和進(jìn)程組還有一些其他特性
1.一個(gè)會(huì)話可以有一個(gè)控制終端(controlling terminal),這通常是終端設(shè)備(在終端登錄)或偽終端設(shè)備(網(wǎng)絡(luò))
2..建立與控制終端連接的會(huì)話首進(jìn)程被稱為控制進(jìn)程(controlling process)
3.一個(gè)會(huì)話中的幾個(gè)進(jìn)程組可被分成一個(gè)前臺(tái)進(jìn)程組(foreground process group)以及一個(gè)或多個(gè)后臺(tái)進(jìn)程
? ?組(background process group)
4.如果一個(gè)會(huì)話有一個(gè)控制終端,則它有一個(gè)前臺(tái)進(jìn)程組,其他進(jìn)程組為后臺(tái)進(jìn)程組
5.無論何時(shí)鍵入終端的中斷鍵,都會(huì)將終端信號(hào)發(fā)送至前臺(tái)進(jìn)程組的所有進(jìn)程
6.如果終端接口檢測(cè)到調(diào)制解調(diào)器(或網(wǎng)絡(luò))已斷開連接,則將掛斷信號(hào)發(fā)送至控制進(jìn)程(會(huì)話首進(jìn)程)
?
?
作業(yè)控制
允許在一個(gè)終端上啟動(dòng)多個(gè)作業(yè)(進(jìn)程組),它控制一個(gè)作業(yè)可以訪問該終端以及哪些作業(yè)在后臺(tái)運(yùn)行。要求以下三種形式的支持:
1.支持作業(yè)控制的shell
2.內(nèi)核中的終端驅(qū)動(dòng)程序必須支持作業(yè)控制
3.內(nèi)核必須提供對(duì)某些作業(yè)控制信號(hào)的支持
?
//這里啟動(dòng)了兩個(gè)作業(yè) pr *.c | lpr & make all & //在后臺(tái)運(yùn)行,之后又將作業(yè)1號(hào)變?yōu)榍芭_(tái)運(yùn)行 cat > temp.foo & fg %1 stty tostop //禁止作業(yè)輸出至控制終端?對(duì)于前臺(tái),后臺(tái)作業(yè)以及終端驅(qū)動(dòng)程序的作業(yè)控制功能總結(jié)
?
?
shell執(zhí)行程序
//執(zhí)行下面這段shell ps -o pid,ppid,pgid,sid,tpgid,comm | cat | cat | tail | more | head //結(jié)果 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
?從結(jié)果中可以看到,所有的命令都父進(jìn)程ID都是bash,也就是bash去啟動(dòng)了那些命令
而ps,cat,cat,tail,more,head這些命令是在一個(gè)進(jìn)程組中的。同時(shí)上面所有的進(jìn)程都是在一個(gè)會(huì)話中
Bourne shell執(zhí)行管道ps | cat1 | cat2時(shí)的進(jìn)程
這里執(zhí)行的sh后,又會(huì)fork一個(gè)新進(jìn)程,然后這個(gè)新的sh進(jìn)程再去fork一些子進(jìn)程,fork的這些子進(jìn)程都是執(zhí)行
sh命令,這些sh命令又調(diào)用exec函數(shù)執(zhí)行不同的shell命令,比如ps,cat這樣的
管道中最后一個(gè)shell命令是由最初的sh(PID為202)調(diào)用exec執(zhí)行的
當(dāng)然這里不同的sh執(zhí)行會(huì)有不同的效果,而且創(chuàng)建的進(jìn)程順序也會(huì)不同
linux上的bash shell對(duì)于所有的執(zhí)行的管道命令都是bash的子進(jìn)程?
?
通過pstree命令執(zhí)行
ps -o pid,ppid,gid,sid,comm | cat | more | head | pstree //結(jié)果 init-+-bash |-6*[mingetty] |-sshd---sshd-+-bash | `-bash-+-cat | |-head | |-more | |-ps | `-pstree `-udevd
可以看到init進(jìn)程for了sshd(也就是終端),然后sshd又fork了bash,
bash調(diào)用exec再fork了cat,head,more,ps等命令,生成相應(yīng)的進(jìn)程
?
?
?
孤兒進(jìn)程組
一個(gè)其父進(jìn)程已經(jīng)終止的進(jìn)程稱為孤兒進(jìn)程(orphan process),這種進(jìn)程由init進(jìn)程收養(yǎng),而整個(gè)進(jìn)程組也有可能成為孤兒。
POSIX.1將孤兒進(jìn)程組(orphaned process group)定義為:
該組中每個(gè)成員的父進(jìn)程要么是該組的一個(gè)成員,要么不是該組所屬會(huì)話的成員。
對(duì)孤兒進(jìn)程組的另一種描述可以使:
一個(gè)進(jìn)程組不是孤兒進(jìn)程組的條件是---該組中有一個(gè)進(jìn)程,其父進(jìn)程在屬于同一會(huì)話的另一個(gè)組中。如果進(jìn)程組
不是孤兒進(jìn)程組,name在屬于同一會(huì)話另一個(gè)組中的父進(jìn)程就有機(jī)會(huì)重新啟動(dòng)該組中停止的進(jìn)程。在這里,進(jìn)程組中每一個(gè)進(jìn)程的父進(jìn)程都屬于另一個(gè)會(huì)話。所以此進(jìn)程組是孤兒進(jìn)程組。
?
?
?
FreeBSD實(shí)現(xiàn)
會(huì)話和進(jìn)程組的FreeBSD實(shí)現(xiàn)
1)s_count是該會(huì)話中的進(jìn)程組數(shù)。當(dāng)此計(jì)數(shù)器減至0時(shí),則可釋放此結(jié)構(gòu)
2)s_leader是指向會(huì)話首進(jìn)程proc結(jié)構(gòu)體的指針
3)s_ttyvp是指向控制終端vnode結(jié)構(gòu)的指針
4)s_ttyp是指向控制終端tty結(jié)構(gòu)的指針
5)s_sid是會(huì)話id
?
tty結(jié)構(gòu)體
1)t_session指向?qū)⒋私K端作為控制終端的session結(jié)構(gòu)(注意,tty結(jié)構(gòu)指向session結(jié)構(gòu),session結(jié)構(gòu)也指向
? ?tty)。終端在市區(qū)載波信號(hào)時(shí)使用此指針將掛起信息發(fā)送給會(huì)話首進(jìn)程
2)t_pgrp是指向前臺(tái)進(jìn)程組的pgrp結(jié)構(gòu)。終端驅(qū)動(dòng)程序用此字段將信號(hào)發(fā)送給前臺(tái)進(jìn)程組。
3)t_termios是包含所有這些特殊字符和與該終端有關(guān)信息(如波特率,回顯打開或關(guān)閉)的結(jié)構(gòu)
4)t_winsize是包含終端窗口當(dāng)前大小的winsize型結(jié)構(gòu)。當(dāng)終端窗口大小改變時(shí),信號(hào)SIGWINCH被發(fā)送至前臺(tái)
? ?進(jìn)程組。
?
pgrp結(jié)構(gòu)體(包含一個(gè)特定進(jìn)程組的信息)
1)pg_id是進(jìn)程組ID
2)pg_session指向此進(jìn)程組所屬會(huì)話的session結(jié)構(gòu)
3)pg_members是指向此進(jìn)程組proc結(jié)構(gòu)表的指針,該proc結(jié)構(gòu)代表進(jìn)程組的成員
?
proc結(jié)構(gòu)體
1)p_pid包含進(jìn)程ID
2)p_pptr是指向父進(jìn)程proc結(jié)構(gòu)的指針
3)p_pglist是一個(gè)結(jié)構(gòu),其中包含兩個(gè)指針,分別指向進(jìn)程組中上一個(gè)和下一個(gè)進(jìn)程
最后還有一個(gè)vnode結(jié)構(gòu),在打開控制終端設(shè)備時(shí)分配此結(jié)構(gòu)體,進(jìn)程對(duì)/dev/tty的所有訪問都通過vnode。
?
?
?
?
?
?
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

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