[APUE]進程關係(上)

来源:http://www.cnblogs.com/orlion/archive/2017/02/24/6440497.html
-Advertisement-
Play Games

一、終端登錄 1. 4.3+BSD終端登錄 系統管理員創建一個通常名為/etc/ttys的文件,其中,每個終端設備有一行,每一行說明設備名和傳到getty程式的參數,這些參數說明瞭終端的波特率。當系統bootstrap時內核創建進程ID 1,也就是init進程。init進程使系統進入多用戶狀態。in ...


一、終端登錄

1. 4.3+BSD終端登錄

  系統管理員創建一個通常名為/etc/ttys的文件,其中,每個終端設備有一行,每一行說明設備名和傳到getty程式的參數,這些參數說明瞭終端的波特率。當系統bootstrap時內核創建進程ID 1,也就是init進程。init進程使系統進入多用戶狀態。init讀文件/etc/ttys,對每一個允許登錄的終端設備,init調用一次fork,它所生成的子進程則執行程式getty。這種情況見下圖:
  


  圖中每個進程的實際用戶ID和有效用戶ID都是0(即都有root許可權)。init以空環境執行getty程式。
  getty對終端設備調用open函數,以讀、寫方式將終端打開。如果設備是數據機,則open可能會在設備驅動程式中滯留,直到用戶撥號數據機,並且線路被接通。一旦設備被打開,則文件描述符0、1、2就被設置到該設備。然後getty輸出"login:"之類的信息,並等待用戶鍵入用戶名。如果終端支持多種速度,則getty可以測試特殊字元以便適當地更改終端速度(波特率)。
  當用戶鍵入用戶名後,getty就完成了,然後它以類似於下列的方式調用login程式:

execle("/usr/bin/login", "login", "-p" username, (char *) 0, envp);

  (在gettytab文件中可能會有一些選擇使其調用其他程式,但系統預設是login程式)。init以一個空環境調用getty。getty以終端名(例如TERM=foo,其中終端foo的類型取自gettytab文件)和在gettytab中的環境字元串為login創建一個環境(envp參數)。-p標誌通知login保留傳給它的環境,也可以將其他環境字元串加到該環境中,但是不要替換它。下圖顯示了login剛被調用後這些進程的狀態。
  


  因為最初的init進程具有root許可權,所以圖中所有進程都有root許可權。圖中底部三個進程的進程ID相同,因為進程ID不會因執行exec而改變。並且除了最初的init進程,所有的進程均有一個父進程ID。
  login能處理多項工作。因為它得到了用戶名,所以能調用getpwnam取得相應用戶的口令文件登陸項。然後調用getpass以顯示提示"Password:"接著讀用戶鍵入的口令。它調用crypt將用戶鍵入的口令加密,並與該用戶口令文件中登陸項的pw_passwd欄位相比較。如果用戶幾次鍵入的口令都無效,則login以參數1調用exit表示登錄過程失敗。父進程(init)瞭解到子進程的終止情況後,將再次調用fork,其後又跟著執行getty,對此終端重覆上述過程。
  如果用戶正確登錄,login就將當前工作目錄更改為用戶的home目錄。它也調用chown改變該終端的所有權,使該用戶成為所有者和組所有者。將對該終端設備的存取許可權改變成:用戶讀、寫和組寫。調用setgid及initgroup設置進程的組ID。然後調用login所得到的所有信息初始化環境:起始目錄(HOME)、shell(SHELL)、用戶名(USER和LOGNAME),以及一個系統預設路徑(PATH)。最後login進程改變為登錄用戶的用戶ID(setuid)並調用該用戶的登陸shell,其方式類似於:

execl("/bin/sh", "-sh", (char *) 0);

  argv[0]的第一個字元是一個標誌,表示該shell被調用為登錄shell。shell可以查看此字元,並相應地修改其啟動過程
  login所做的比上面說的要多。
  到此為止,登錄用戶的登錄shell開始運行。其父進程ID是init進程ID(進程ID 1),所以當此進程終止時,init進程會收到通知(接收到SIGGHLD信號),它會對該終端重覆全部上述過程。登陸shell的文件描述符0,1和2設置為終端設備。下圖顯示了這種安排。
  

 


  現在登錄shell讀其啟動文件。這些啟動文件通常改變某些環境變數,加上一些環境變數。當執行完啟動文件後,用戶最後得到shell的提示符,並能鍵入命令。

2. SVR4終端登錄

  SVR4支持兩種方式的登錄:(a)getty方式,這與上面的一樣。(b)ttymon登錄,這是SVR4的一種新功能。通常getty用於控制台,ttymon則用於其他終端的登錄。

二、網路登錄

1. 4.3+BSD網路登錄

  終端登錄時,init知道哪些終端設備可用來登錄,併為每一個設備生成一個getty進程。但是網路登錄都經過內核的網路界面驅動程式,事先並不知道有多少個這樣的登錄。不是使一個進程等待每一個可能的登錄,而是必須等待一個網路連接請求的到達。在4.3+BSD中,有一個稱為inetd的進程,它等待大多數網路連接。
  作為系統啟動的一部分,init調用一個shell,使其執行shell腳本stc/rc。由此shell腳本啟動一個精靈進程inetd。一旦此shell腳本終止,inetd的父進程就變成init。inetd等待TCP/IP連接請求到達主機,而當一個連接請求到達時,它執行一次fork,然後該子進程執行適當的程式。
  我們假定到達了一個對於TELNET伺服器的TCP連接請求。TELNET是使用TCP協議的遠程登錄應用程式。在另一個主機上的用戶,或在同一個主機上的用戶啟動TELNET客戶端進程啟動登錄過程:

telnet hostname

  該客戶端進程打開一個到名為hostname的主機的TCP連接,在hostname主機上啟動的程式被稱為TELNET伺服器。然後客戶端進程和伺服器進程之間使用TELNET應用協議通過TCP連接交換數據。所發生的是啟動客戶端進程的用戶現在登錄到了伺服器進程所在的主機。下圖顯示了在執行TELNET伺服器進程(稱為telnetd)中所涉及的進程式列。
  


  然後telnetd進程打開一個偽終端設備,並用fork生成一個子進程。父進程處理通過網路連接的通信,子進程則執行login程式。父、子進程通過偽終端相連接。在調用exec之前,子進程使其文件描述符0,1,2與偽終端相連。如果登錄正確,login就執行:更改當前工作目錄為起始目錄,設置登錄用戶的組ID和用戶ID,以及登錄用戶的起始環境。然後login用exec將其自身替換為登錄用戶的登錄shell。下圖顯示了到達這一點時的進程安排
  


  當通過終端或網路登錄時,我們得到一個登錄shell,其標準輸入、輸出和標準出錯連接到一個終端或者偽終端設備上。

2. SVR4網路登錄

  SVR4中網路登錄的情況與4.3+BSD中的幾乎一樣。同樣使用了inetd伺服器進程,但是在SVR4中inetd是作為一種服務存取控制器sac調用的,其父進程不是init。最後得到的結果與上圖一樣。

三、進程組

  每個進程除了有一進程ID之外,還屬於一個進程組,進程組是一個或多個進程的集合,每個進程組有一個唯一的進程組ID。進程組ID類似進程ID,它是一個正整數,並可存放在pid_t數據類型中。函數getpgrp返回調用進程的進程組ID

#include <sys/types.h>
#include <unistd.h>

pid_t getpgrp(void);
返回值: 調用進程的進程組ID

  每個進程組都有一個組長進程。組長進程的標識是:其進程組ID等於其進程ID。
  進程組組長可以創建一個進程組,創建該組中的進程,然後終止。只要在某個進程組中有一個進程存在,該進程組就存在,與進程組長是否終止無關。從進程組創建到其中最後一個進程終離開(該進程可以終止也可以加入另一個進程組)的時間區間稱為進程組的生命期。
  進程調用setpgid可以參加一個現存的組或者創建一個新進程組

#include <sys/types.h>
#include <unistd.h>

int setpgid(pid_t pid, pid_t pgid);
返回值: 若成功則為0,出錯為-1

  這將pid進程的進程組ID設置為pgid。如果這兩個參數相等,則由pid指定的進程變成進程組組長。
  一個進程只能為它自己或它的子進程設置進程組ID。在它的子進程調用了exec後,它就不再改變該子進程的進程組ID
  如果pid是0,則使用調用者的進程ID。如果pgid是0,則由pid指定的進程ID被用作為進程組ID。
  如果系統不支持作業控制,那麼就不定義_POSIX_JOB_CONTROL,在這種情況下,該函數返回錯誤,errno設置為ENOSYS。
  在大多數作業控制shell中,在fork之後調用此函數,使父進程設置其子進程的進程組ID,然後使子進程設置其自己的進程組ID。這些調用中有一個是冗餘的,但這樣做可以保證父、子進程在進一步操作之前,子進程都進入了該進程組。如果不這樣做的話,那麼就產生一個竟態條件,因為它依賴於哪一個進程先執行。

四、對話期

  對話期(session)是一個或多個進程組的集合。例如,可以有下圖中所示的安排。在一個對話期中有三個進程組。通常由shell的管道線將幾個進程編成一組的。例如下圖中的安排可能是由下列形式的shell命令形成的:

proc1 | proc2 &
proc3 | proc4 | proc5

  


  進程調用setsid函數就可以建立一個新對話期。

#include <sys/types.h>
#include <unistd.h>

pid_t setsid(void);
返回值:若成功則為進程組ID,若出錯則為-1

  如果調用此函數的進程不是一個進程組的組長,則此函數創建一個新對話期,結果為:

  1. 此進程變成該新對話期的對話期的首進程(session leader, 對話期首進程是創建該對話期的進程)。此進程是該新對話期中的唯一進程。
  2. 此進程成為一個新進程組的組長進程。新進程組ID是此調用進程的進程ID。
  3. 此進程沒有控制終端。如果在調用setsid之前此進程有一個控制終端,那麼這種聯繫也被解除。

  如果此調用進程已經是一個進程組的組長,則此函數返回出錯。為了保證不處於這種情況,通常先調用fork,然後使父進程終止,而子進程則繼續。因為子進程繼承了父進程的進程組ID,所以其不可能是進程組組長。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 寫在前面:當你部署一臺伺服器,第一步不應該是部署應用,安全是才是首要任務 如果某一天當你登錄伺服器發現 /bin/bash –i,python -c 'import pty; pty.spawn("/bin/sh")' 等命令在伺服器上出現的時候,那麼恭喜你,伺服器被入侵了 但是入侵者都是很聰明的, ...
  • ownCloud(官網)是一款開源的私有雲框架,可以通過它實現個人網盤的功能,如果擁有一個性能不錯的VPS,那麼就可以擺脫奇慢無比的百度雲等網盤啦!我花了大約一天的時間總算搭好了ownCloud。 ...
  • 作者信息 作者: 彭東林 郵箱: [email protected] QQ: 405728433 軟體平臺 主機: Ubuntu14.04 64位版本 模擬器:Qemu-2.8.0 Linux內核版本: Linux-4.10 Busybox版本:busybox-1.24.2 工具鏈: ar ...
  • 1、經典入門:hello world 註:上面所使用的關鍵字:include 頭文件包含 int 整型,用來表示整數的類型 void 空類型 return 函數返回 2、基本概念: 源文件:源文件即源程式代碼文件,C語言源文件尾碼名是.c; 頭文件:頭文件的尾碼名為.h,C語言代碼由源文件和頭文件構 ...
  • 第十七節 精簡shell基礎 標簽(空格分隔): Linux實戰教學筆記 1,前言 1.1 為什麼學習shell編程 Shell腳本語言是實現Linux/UNIX系統管理及自動化運維所必備的重要工具,Linux/UNIX系統的底層及基礎應用軟體的核心大部分涉及Shell腳本的內容。每一個合格的Lin ...
  • MySQL資料庫 第一條產品線:5.0.xx及升級到5.1.xx的產品系列,這條產品線繼續完善與改進其用戶體驗和性能,同時增加新功能。 第二條產品線:為了更好地整合MySQL AB公司社區和第三方公司開發的新存儲引擎,以及吸收新的實現和演算法等,從而更好地支持SMP架構,提高性能而做了大量的代碼重構。... ...
  • Nginx配置同一個功能變數名稱http與https兩種方式都可訪問,證書是阿裡雲上免費申請的 server{listen 80;listen 443 ssl;ssl on;server_name 功能變數名稱;index index.html index.htm index.php default.html de ...
  • 在IIS7+上導出所有應用程式池的方法:%windir%/system32/inetsrv/appcmd list apppool /config /xml > c:/apppools.xml 這個命令會將伺服器上全部的應用程式池都導出來,但有些我們是我們不需要的,要將他們刪掉.比如:Default ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...