亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Linux會話淺析

2019-11-11 03:55:38
字體:
來源:轉載
供稿:網友
說起會話,我們經常登錄到linux系統,執行各種各樣的程序,這都牽涉到會話。但是,一般情況下我們又很少會去關注到會話的存在,很少會去了解它的來龍去脈。本文就對linux會話相關的信息做一些整理,看看隱藏在我們日常使用的背后,都有些什么樣的邏輯?!緯挼木S系】維系一個會話,最常見的有兩種方式:一是基于某種憑證,比如web網站的登錄會話,在登錄驗證之后,服務器就會返回一個session id作為憑證。用戶之后的請求總是會帶上這個id,而服務器通過這個id也就能知道用戶是誰。直到用戶注銷登錄、或者登錄超時,服務器會清洗掉對應的session id,這個id就失效了,會話也就隨之而結束。第二種方式是基于連接的,當用戶和系統之間的連接啟用時,系統會對用戶進行驗證,驗證通過之后,來自這個連接的操作都是屬于這個用戶的。直到連接斷開,則會話結束。linux系統的會話就是以第二種方式來維系的。會話基于連接,那么連接的安全性就決定了會話的安全性。以最常見的兩種連接為例:1、本地連接,用戶是直接通過鍵盤顯示器來跟系統交互的,鍵盤顯示器直接連接在主機上,連接被篡改基本上是不可能的;2、遠程連接,以ssh為例,其協議會進行加密,從而避免連接被篡改;下面在討論會話的時候就圍繞兩種連接來展開?!具B接的啟用】前面說到,會話是基于連接的。會話的源頭,就是用戶與系統之間連接的啟用。對于本地連接,連接是在系統初始化時建立的。linux會初始化若干個tty(/dev/tty?),形成若干個虛擬終端。本地連接的鍵盤和顯示器通過對應的驅動程序,跟其中某個tty綁定上。用戶可以通過ALT+F[1-12]鍵,將鍵盤和顯示器切換到不同的tty上(也就是說,一套鍵盤顯示器可以對應多個本地連接)。在系統啟動的時候,init程序會根據相應的配置(如:/etc/init/tty1.conf),啟動相應的程序來監聽這些tty(如:/sbin/getty -8 38400 tty1。下文說到這個監聽程序時,就以getty為例)。當用戶通過ALT+F?切換到對應的tty?、并有所輸入時,在該tty上監聽的getty就能讀取到輸入信息,然后通過exec啟動login程序來進行登錄驗證。從getty得到輸入的這一刻起,tty?上的這個連接就算是啟用了。對于遠程連接,本文都以ssh為例。系統安裝ssh server之后,在/etc/init.d/下會有它對應的啟動腳本,這會使得sshd程序(ssh服務器)在系統啟動的時候被啟動(當然,root用戶也可以在系統啟動之后,手動啟動sshd)。sshd監聽網絡上的相應端口(如:tcp:22),等待遠程用戶的連接。用戶的連接始于TCP連接,然后sshd和ssh-client會打通ssh隧道。從這時起,連接啟用,sshd會要求用戶進行登錄驗證?!镜卿涷炞C】不管是本地終端登錄,還是遠程登錄,登錄驗證無非就是要讓用戶輸入用戶名和密碼。用戶輸入的信息通過已經啟用的連接到達對端程序(如:login、sshd),然后由其進行校驗。系統中的用戶信息存放在/etc/passwd文件中,里面保存的系統中所有用戶的信息。這些信息主要有:用戶名、密碼、組、home路徑、以及登錄后執行的程序、等。這些信息可以分兩個層面來看:一、用于驗證的。包括用戶名和密碼兩項。即用戶在與系統建立連接后,需要提供用戶名和密碼來進行驗證(注意,密碼一般并不是明文保存在passwd文件中的);二、登錄后用于設置用戶屬性的。除密碼外的所有項。下面會詳細解釋;用戶登錄后會得到一個進程,關于這個進程,它有如下一些特征:1、對于本地連接,它就是原本執行getty的那個進程;而對于ssh連接,它是由sshd fork出來的進程;2、進程的用戶名、組、當前路徑、等都被按/etc/passwd文件中的描述進行設置;3、進程的stdin、stdout、stderr連接到一個對應的終端。對于本地連接,這個終端就是getty監聽的那個tty;對于ssh連接,它是由sshd打開的pty(偽終端,后面會詳細解釋);4、這個進程會執行/etc/passwd中配置的"登錄后執行的程序",這個程序一般就是/bin/sh,即登錄后為用戶提供一個shell控制臺。于是用戶可以使用自己的終端跟這個shell程序交互,干各種事情。這個"登錄后執行的程序"也常被配置為/bin/nologin,表示對應用戶是不允許登錄的,因為nologin程序不會與用戶進行交互,打印錯誤信息后就會退出了,所以登錄只是白費勁。當然,如果你愿意,并且有root權限,也可以將"登錄后執行的程序"配置成其他程序;于是,用戶在登錄完成之后,系統中就存在這樣一個用戶名為該登錄用戶的進程。通常這個進程運行shell程序,并且其輸入輸出連接到用戶的終端,所以用戶可以用鍵盤來操作這個shell,并且用顯示器接收shell的輸出?!娟P于終端】前面講到,登錄后的shell其輸入輸出是連接到用戶使用的終端的,不管是本地登錄的tty,還是遠程登錄的pty。但是,為什么要有終端呢?shell的輸入直接接到鍵盤、輸出直接接到顯示器,這樣不行么?尤其是遠程的情況,shell的輸入輸出為什么不能直接接到網絡,而非要弄一個pty出來呢?最容易想到的一點,終端能夠使得上層不必關心輸入輸出設備本身的細節,只管對其讀寫就行了。不過這一點似乎并不是終端所特有的,因為vfs已經能夠勝任了。應用程序open設備文件,得到fd,然后同樣只用管對其讀寫就行了,而不用關心這個fd代表的是鍵盤、還是普通文件,具體的細節已經被隱藏在設備驅動程序之中。不過,相比于普通的讀寫,終端還實現了很多可以通過ioctl系統調用進行配置的功能,能夠完成一些針對輸入輸出的處理邏輯。如:1、回車換行的轉換:定義輸入輸出如何映射回車換行符。比如:回車鍵是/r、還是/n、還是/r/n;再如:/n應該如何打印到屏幕上,是回車+換行、還是只換行不回車、等等;2、行編輯:允許讓輸入字符不是立馬送到應用程序,而是在換行以后才能被讀取到。未換行的輸入字符可以通過退格鍵進行編輯(比如在你密碼輸錯的時候,是可以用CTRL+退格來進行編輯的);3、回顯:可以讓輸入字符自動被回顯到終端的輸出上。于是,鍵盤每輸入一個字符都能在顯示器上看到它,而這些字符其實很可能是還沒被應用程序讀取到的(因為有行編輯);4、功能鍵:允許定義功能鍵。比如最常用的Ctrl+C,殺死前臺進程,就是由終端來觸發的。終端檢測到Ctrl+C輸入,會向前臺進程組發送SIGTERM信號。而誰是前臺進程組呢?這是由shell通過ioctl系統調用對終端使用TIOCSPGRP命令來設置的,每當shell啟動一個前臺進程,它都需要這么設置一下;5、輸入輸出流向控制,只有前臺進程組能夠從終端中讀數據、而不管前臺后臺程序都能向終端寫數據。這點也是必須的,跟用戶進程交互的是前臺進程,用戶的輸入當然不能被其他后臺進程搶走。但是一個進程是前臺還是后臺,是它自己是所不知道的,沒法靠進程自己來判斷什么時候可以讀終端、什么時候不能讀。所以需要終端來提供支持,如果后臺進程讀這個終端,終端的驅動程序將向其發送SIGTTIN信號,從而將其掛起。直到shell將其重新置為前臺進程時(通過fg命令),該進程才會繼續執行;6、等等;終端提供的這些功能未必都會被打開它的程序使用到,但是如果要使用,則可以通過統一的ioctl接口來設置,而不需要關心終端具體接的是什么設備,是鍵盤顯示器?還是網絡。大多數應用程序則根本不關心終端,只當它是能夠滿足讀寫需求的文件。而像shell這樣為人機交互而生的程序,則注定會跟終端打交道。對于shell來說,像“行編輯”、“回顯”這樣的功能,其實是可以不需要依賴終端的,shell程序自己可以做這樣的處理,因為要做處理的數據正是shell從終端里面讀到的數據。但是像“功能鍵”、“輸入輸出流向控制”這樣的功能,則又不得不依賴終端。比如“功能鍵”,因為這時在對終端進行讀操作的是shell啟動的前臺程序,而不是shell自己,所以不可能由shell來讀取功能鍵,然后觸發信號??梢哉f,終端是人機交互時,應用程序與用戶之間的一個中間層。如果應用程序是在跟人交互,使用終端是其不二的選擇;否則則沒有必要使用終端。這一點在sshd上面有很好的體現。當用戶使用ssh登錄到遠程機器remotehost,并執行一些操作時(比如執行cat test.txt操作),可以有兩種方式:1、ssh user:pass@remotehost,遠程登錄后,再在shell中執行cat test.txt命令;2、ssh user:pass@remotehost 'cat test.txt',直接由sshd啟動一個shell、自動執行'cat test.txt'命令;第一種方式,是登錄之后,再通過人機交互輸入命令,這時sshd會為登錄后得到的shell程序準備一個pty,以支持人機交互;而第二種方式,在登錄之后并不需要交互,所以sshd就并不會使用pty,而是直接通過socket將shell的輸入輸出跟自己連接起來(再由sshd將其轉發給ssh-client)。下面再說一下pty。pty分master和slave兩端,跟pipe的兩端很像,寫入到master端的數據可以原樣從slave端讀出,反之亦然。在上面所述的第一種方式下,各個進程的聯系如下:ssh-client <-> [socket] <-> sshd <-> [master] <-> [slave] <-> shellpty的master和slave兩端分別被sshd和shell打開,就像pipe一樣,將它們的輸入輸出連接起來。而pty跟pipe的不同之處,則正是前面所說的終端的功能(pty的slave端對于shell來說就是一個終端)。跟tty不同,tty是系統初始化時生成的,其數目是固定的(比如12個)。而pty是系統啟動后動態創建的。其創建的方法是:fd = open('/dev/ptms'),這樣就得到了一個pty。open返回的fd代表master端,通過ptyname(fd)可以得到對應slave端的文件路徑(比如'/dev/pts/2'),這個設備文件是master端被open之后動態生成的?!緳嘞蘅刂啤坑脩舻卿涷炞C成功后,getty、sshd這樣的程序就會為用戶啟動他所對應的"登錄后執行的程序",并且在此之前會通過setuid()、setgid()這樣的系統調用,設置好進程的uid和gid(用戶和組)。之后,這個進程對文件的讀、寫、執行,以及對系統調用的使用,等都會受到進程uid和gid的限制。用戶對系統的各種操作都是通過進程來完成的。而用戶的輸入輸出都被定向到他登錄后所得到的那個進程上,于是用戶能夠控制這個進程,來干他想干的事情(如果這個進程接受控制的話,比如進程運行著一個shell程序)。用戶的操作都受限于進程的uid和gid,比如文件訪問、向進程發送信號、使用系統調用、監聽網絡端口、等都需要對其做檢查。除非是root用戶,否則沒有權限使用setuid()、setgid()這樣的系統調用來修改進程的uid和gid。而login時,login、sshd這樣的進程之所以能夠設置登錄后進程的uid和gid,正是因為它們都是root用戶的進程。如果想要改變登錄用戶,則必須利用屬于root用戶的進程。一種辦法是退出登錄,然后走老路,重新跟getty、sshd這樣的進程打交道,而使用其他用戶名登錄。另一種辦法是執行一個setuid/setgid程序(參見《記一個linux內核內存提權問題》中的說明),臨時獲得root權限,再實現用戶的切換(例如su就是這樣一個能實現用戶切換的setuid命令)。為了實現進程權限控制中的各種功能,進程的uid和gid其實并不止一組,主要有如下三組:1、ruid/rgid,代表實際的用戶和組id;2、euid/egid,代表當前生效的用戶和組id;3、suid/sgid,代表保留的用戶和組id;什么意思呢?一般情況下,在用戶登錄得到的進程中,這三組id都是相同的值,與登錄用戶相對應(假設為aaa)。而用戶新創建的進程也會全部繼承這三組id。當用戶執行一個setuid/setgid程序時,執行程序的進程將得到可執行程序owner(假設為bbb)的用戶屬性,euid/egid和suid/sgid會更新為bbb(而ruid/rgid不會被更新)。這些id在進程操作別的對象時(比如寫文件、發信號、等)或被別的進程操作時(比如其他進程向其發信號、等)會被用做校驗。ruid/rgid和euid/egid在進程被操作的時候會使用到,euid/egid在進程發起操作的時候會用到。比如有一個進程,其ruid是aaa、euid是bbb,則euid為aaa或bbb的其他進程都可以向其發送信號。而該進程在進行讀寫文件、創建文件、等操作時,使用的則是用戶bbb的權限:它創建的文件owner是bbb、它在訪問owner是aaa的文件時以other權限進行校驗。那么第三組id,suid/sgid又是干什么用的呢?之前說普通用戶沒有權限使用setuid()這樣的系統調用來改變進程的uid和gid,其實這個說法并不確切。進程其實是有權限將自己的ruid/rgid、euid/egid、suid/sgid的值修改成與這三者之一相等的值。比如ruid/rgid為aaa、suid/sgid為bbb,則用戶可以任意將euid/egid設置為aaa或bbb。因為大多數情況下這三組id是等值的,所以一般說用戶進程不能修改自己的uid和gid(只能從aaa修改為aaa,相當于不能修改)。但是執行setuid的程序后,進程的這三組id就有了兩種不同的取值,ruid/rgid等于aaa、euid/egid和suid/sgid等于bbb,于是進程的uid就有了一定的選擇余地。比如此時進程的euid/egid被更新成了bbb,那就不能再以owner身份去操作aaa的文件了(注意,這個進程原本是以aaa用戶登錄而得到的)。不過沒關系,進程是有權限將euid/egid改回aaa的,因為ruid/rgid的值是aaa。但是改回來之后,ruid/rgid和euid/egid都是aaa了,要再想把euid/egid改為bbb怎么辦呢?suid/sgid就是為此而生的,作為一個備份,它的值是bbb,這使得euid/egid還能夠修改回bbb。當然,進程也有權限將euid/egid和suid/sgid都改回aaa,這將使得它們不再能修改成bbb了。【會話退出】用戶登錄是一個會話的開始。登錄之后,用戶會得到一個跟用戶使用的終端相連的進程,這個進程被稱作是這個會話的leader,會話的id就等于該進程的pid。由該進程fork出來的子進程都是這個會話的成員(進程的sid等于該會話id)。leader進程的退出,將導致它所連接的終端被hangup,這意味著會話結束。反過來,像ssh這樣的遠程連接也可以通過斷開連接的方式來使終端hangup,這將使得leader進程收到SIGHUP信號而退出。如果會話使用的是pty,其本身是隨會話的建立而創建出來的,會話結束,則pty被銷毀;而如果會話使用的是tty,其本身是在系統初始化時創建的,并不依賴于會話的建立,則會話結束時,tty依然存在。init進程檢測到使用該tty的會話已經結束,便會重新啟動一個getty來監聽該tty。不過,會話結束,并不意味著在該會話中創建的所有進程都結束了。所謂的daemon進程,正是在某個會話中創建,但是卻不依賴該會話,而常駐后臺的進程。具體來說,當終端hangup時,內核會有如下兩個動作:1、向對應會話的leader進程發送SIGHUP信號。而一般來說,會話的leader進程很可能是一個shell,它在收到SIGHUP信號后,并不是馬上退出,而是會向它所啟動的子進程都各自發送一個SIGHUP信號,將它們都殺死,然后自己才退出。不過,如果是這個作為leader進程shell自己退出,而導致終端hangup的話,向其子進程發送SIGHUP信號的事情就不會發生了,因為shell退出在先,它再也不會收到SIGHUP信號;2、修改所有打開該終端的文件句柄,改成一個不可讀不可寫的實現;所以,在會話退出之后還常駐后臺的進程肯定是沒法跟終端交互的。而要想讓進程常駐后臺,一般有如下幾種方法:1、避免shell發SIGHUP信號;主要有兩種辦法:1)主動exit,而不是直接斷開終端;2)兩次fork。因為shell只認識它自己fork出來的子進程,并不知道"子又生孫"的事情,也就不會給孫子進程發送SIGHUP信號了;2、忽略SIGHUP信號;終端hangup時進程可能收到shell發送的SIGHUP信號。信號的默認處理動作是退出進程,但是該信號是可以忽略的。忽略信號,就可以使得后臺進程不會隨會話退出而退出。nohup命令就是做這件事情的,而且它做得更完整一些,不僅忽略SIGHUP,還會將進程的標準輸入重定向為/dev/null、輸出重定向到nohup.out文件;3、使用setsid()系統調用,為進程開啟一個新的會話;從一個會話中fork出來的進程,默認都是屬于這個會話的。但是進程可以調用setsid(),使自己脫離原先的會話,而成為一個新會話的leader。于是,原先的會話退出,就不會影響到新建的會話了。setsid命令包裝了setsid()系統調用,可以為進程創建新的會話。不過它并不對新進程的輸入輸出進行重定向,這就意味著新進程的輸入輸出還是連接到原先的那個tty的,這可能跟原先的會話爭搶輸入。所以,對新會話的進程進行輸入輸出的重定向也是一件很重要的事情。一個進程成為daemon進程,可以不隨會話的退出而退出,但是進程的uid/gid并不會因此而改變。對應的用戶還可以在其他會話中,通過發信號等方式,操作那些原來由他所啟動的daemon進程(因為權限控制是以用戶為準的,而并不考慮會話)。
上一篇:篩法

下一篇:簡單的輸入輸出流(2)

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲视频一区二区三区| 国产视频精品一区二区三区| 久久激情视频久久| 欧美日韩亚洲网| 51精品在线观看| 国产精品亚洲欧美导航| 日韩av毛片网| 中文字幕在线成人| 中文日韩在线视频| 日韩国产中文字幕| 日韩精品在线看| 福利一区福利二区微拍刺激| 亚洲国产精品女人久久久| 欧美性xxxx在线播放| 国产日韩精品在线观看| 国产成人精品一区二区三区| 日韩精品一二三四区| 日韩视频永久免费观看| 成人黄色av网站| 91sao在线观看国产| 中文字幕av一区二区三区谷原希美| 亚洲一二在线观看| 亚洲色图第一页| 中文字幕精品在线| 亚洲成人av片在线观看| **欧美日韩vr在线| 亚洲福利视频免费观看| 97视频免费观看| 亚洲第一精品电影| 7777免费精品视频| 精品国产乱码久久久久久天美| 国产精品入口福利| 亚洲自拍偷拍网址| 日韩在线一区二区三区免费视频| 欧美激情极品视频| 国产美女扒开尿口久久久| 高跟丝袜欧美一区| 日韩av电影国产| 26uuu另类亚洲欧美日本老年| 欧美成人一区二区三区电影| 日韩一二三在线视频播| xxxxx91麻豆| 欧美丰满老妇厨房牲生活| 欧美国产视频一区二区| 国产精品福利在线| 91在线高清视频| 午夜精品久久久久久久久久久久久| 亚洲三级黄色在线观看| 亚洲欧美国产日韩中文字幕| 亚洲а∨天堂久久精品喷水| 亚洲精品一二区| 亚洲国产精品成人精品| 91热精品视频| 亚洲奶大毛多的老太婆| 日韩欧美亚洲范冰冰与中字| 国产成人一区二区三区| 欧美大片免费看| 久久亚洲精品国产亚洲老地址| 日韩av影视综合网| 欧美三级免费观看| 国产精品第一页在线| 日韩欧美一区二区三区| 亚洲精品国产精品乱码不99按摩| 久久韩国免费视频| 日韩日本欧美亚洲| 亚洲精品丝袜日韩| www.欧美三级电影.com| 亚洲精品视频网上网址在线观看| 国产91ⅴ在线精品免费观看| 这里只有精品在线播放| 国产小视频国产精品| 成人av.网址在线网站| 久久精品国产亚洲7777| 国产91精品最新在线播放| 国内精品伊人久久| 黄色成人av在线| 久久久91精品国产一区不卡| 欧美激情一区二区三区高清视频| 国产亚洲日本欧美韩国| 亚洲精品久久久久久久久| 欧美日韩国产成人高清视频| www.久久久久久.com| 午夜精品视频网站| 国产精品啪视频| 日韩美女视频免费看| 久久精品国产电影| 96国产粉嫩美女| 国产精品成人av在线| 久久久国产精品免费| 国产丝袜一区二区三区免费视频| 亚洲少妇中文在线| 国产成人在线一区| 韩国视频理论视频久久| 成人激情在线观看| 国产精品综合不卡av| 久久五月情影视| 欧美日韩999| 国产成人精品国内自产拍免费看| 亚洲天堂av在线免费观看| 俺也去精品视频在线观看| 97**国产露脸精品国产| 久久深夜福利免费观看| 在线电影av不卡网址| 丝袜美腿亚洲一区二区| 最近2019年好看中文字幕视频| 成人免费大片黄在线播放| 成人激情视频在线观看| 国产成人午夜视频网址| 精品爽片免费看久久| 疯狂做受xxxx高潮欧美日本| 日韩毛片在线看| 国内精品久久久久久久| 国产91精品最新在线播放| 欧美在线www| 亚洲欧美日韩精品久久| 国产香蕉一区二区三区在线视频| 亚洲精品成a人在线观看| 亚洲精品久久久久| 久久免费视频在线观看| 日韩欧美中文字幕在线观看| 成人久久18免费网站图片| 色久欧美在线视频观看| 精品国产一区av| 国产成人精品一区二区在线| 91精品国产综合久久男男| 91精品在线播放| 成人a视频在线观看| 中文字幕亚洲欧美日韩在线不卡| 亚洲国产99精品国自产| 伊人久久男人天堂| 国外视频精品毛片| 性色av一区二区三区在线观看| 国产精品美女无圣光视频| 国产精品丝袜高跟| 亚洲成人久久久| 欧美亚洲日本黄色| 精品中文视频在线| 97视频免费在线看| 91中文精品字幕在线视频| 亚洲网在线观看| 欧美一区二区三区精品电影| 日韩小视频网址| 亚洲激情中文字幕| 国产日韩精品在线观看| 97在线免费观看视频| 国产欧美一区二区三区在线| 亚洲一区亚洲二区亚洲三区| 一本色道久久88精品综合| 国产精品96久久久久久又黄又硬| 日本午夜精品理论片a级appf发布| 91社区国产高清| 亚洲成人a级网| 夜夜躁日日躁狠狠久久88av| 久久97久久97精品免视看| 国产在线观看精品| 久久天天躁狠狠躁老女人| 久久综合国产精品台湾中文娱乐网| 亚洲最大福利网站| 国产精品爱啪在线线免费观看| 97成人超碰免| 亚洲毛片一区二区| 欧美三级免费观看| 午夜欧美不卡精品aaaaa| 成人性生交大片免费看视频直播|