《Linux源碼分析報(bào)告——字符終端設(shè)備》由會員分享,可在線閱讀,更多相關(guān)《Linux源碼分析報(bào)告——字符終端設(shè)備(6頁珍藏版)》請?jiān)谘b配圖網(wǎng)上搜索。
1、
源碼分析報(bào)告——字符終端設(shè)備
字符終端設(shè)備的打開操作
當(dāng)我們需要使用一個字符終端設(shè)備的時(shí)候,首先需要打開它。而打開這一動作,在下面通常是由一些守護(hù)進(jìn)程所發(fā)起的,比如當(dāng)我們在登錄到一個虛終端的時(shí)候,通常是由一個進(jìn)
程來打開這個虛終端(從 的的版本開始,開始改用另一個較小的程序來實(shí)現(xiàn)相同的功能) ,是被進(jìn)程所發(fā)起的進(jìn)程,它完成以下的操作:
. 打開行設(shè)備并設(shè)置它們的模式;
.打印出的提示符,并得到用戶名;
.為用戶發(fā)起一個進(jìn)程為用戶進(jìn)行登錄
()流程:
我們從程序調(diào)用函數(shù)
2、打開一個終端設(shè)備開始。
() ("");
()
()
很簡單,得到一個空閑 ,設(shè)置一些參數(shù),然后調(diào)用 ():
(, )
()
() ;
先獲得一個空閑結(jié)構(gòu);
填充這個結(jié)構(gòu);
調(diào)用獲得設(shè)備文件的;
繼續(xù)填充結(jié)構(gòu);
這之中調(diào)用了 >>() 來執(zhí)行下層的打開操作,下面才真正涉及到終端的 ()
()
( * , * )
、首先通過取得
;
>;
注:即先取得所指向的設(shè)備的設(shè)備號;再根據(jù)當(dāng)前的終端類型生成新的主、從設(shè)備號;
、調(diào)用 ()函數(shù)得到結(jié)構(gòu)。把它賦給 >
(, );
(
3、)
1 / 6
;
> ;
、調(diào)用檢查 >是否真正表示了內(nèi)存中打開該的。大概是出于完整性的考慮。
、調(diào)用 >的 ()函數(shù)。
>(, );
具體說來,每一個不同的,有不同的執(zhí)行相應(yīng)操作的函數(shù),詳見附錄。
、將賦給結(jié)構(gòu)。
> ;
> ;
> >;
> >;
()
( , **)
本函數(shù)包括主要的的操作。
本函數(shù)使用了一個來互斥操作。 ; 在函數(shù)的開始調(diào)用 () 進(jìn)入臨界區(qū)在函數(shù)的結(jié)尾調(diào)用 ()
退出臨界區(qū)。
為了實(shí)現(xiàn)干凈操作,本函數(shù)先分配內(nèi)存,再進(jìn)行關(guān)鍵操作,若出現(xiàn)錯
4、誤,則先到 : 區(qū),釋放出
所有分配的內(nèi)存,再退出。
現(xiàn)在講述程序的操作流程。
、根據(jù)設(shè)備號得到設(shè)備的結(jié)構(gòu)。
();
、進(jìn)入臨界區(qū)
();
、若該不是第一次打開,轉(zhuǎn)到 ( ). 否則,繼續(xù)。
>[];
() ;
、第一次打開的操作比較復(fù)雜。
主要為申請?jiān)O(shè)置結(jié)構(gòu),值得注意的是 > []; 表明所有的開始都用相同的結(jié)構(gòu)。而最終都調(diào)用的讀寫函數(shù),體現(xiàn)了只是一個虛擬終端的思想。
5 、調(diào)用 >中的 ()函數(shù)。
6 、 >,計(jì)數(shù)。
7 、退出臨界區(qū)
();
;
8 、返回。
()
這個函數(shù)
5、在 >中被調(diào)用。
( *)
設(shè)置的底層讀寫參數(shù)(大多與讀寫有關(guān)) 。如:讀寫緩沖,結(jié)構(gòu)的參數(shù)。
>()
2 / 6
如前文所示: ( )在第四步會調(diào)用 >( ),對于不同類型的來說,這里相應(yīng)的 >( )當(dāng)然也會有所不
同,下面列舉了一些對應(yīng)于不同 類型的不同操作,同時(shí)我們也看到在 ()中會調(diào)用 >() ;下面
是面向不同行設(shè)備的相應(yīng)操作。
對應(yīng)于不同的類型的 >():
;
;
;
;
;
;
;
;
對應(yīng)于不同類型的 >();
如果是
6、,則有 ;
;
若為則為:的初始化詳見后面的說明。
;
;
如果是串行的設(shè)備則為:
;
;
在里面:
;
;
字符終端設(shè)備的寫操作
程序中的兩個重要數(shù)據(jù)結(jié)構(gòu)
{
*(*)();
(*)(
*, );
(*)(
*);
(*)(
*, , , , );
(*)(
*, , , );
(*)(
*,
*, , , );
(*)(
*, );
(*)(
*, , , , );
(*)(
*, , , , , , );
7、
(*)(
*);
3 / 6
(*)(
*, );
(*)(
*,
*);
(*)(
*,
*);
(*)(
*, );
(*)(
*);
(*)(
*);
(*)(
*, , , , , );
(*)(
*,
*, );
};
{
; * *
; * , ... *
;
;
;
*;
} *[];
()的流程
我們從程序調(diào)用 ()開始。
調(diào)用 ()函數(shù)。
()
()
8、此函數(shù)中調(diào)用具體的 () 函數(shù)。
(>);
>>();
(>);
()
( * , * , * , )
首先從 >里面取出一個結(jié)構(gòu),得到相關(guān)的的信息,
此函數(shù)中調(diào)用 ()
(>,
, , ,
( *),
( ));
(>, , 最后調(diào)用 ()
注:大概考慮到一次不能寫太多字符中將字符分批輸出。
反復(fù)調(diào)用傳來的函數(shù): (, , , );
4 / 6
這個函數(shù)其實(shí)就是 >,即 ()
()
( * , * ,
* , )
注:此函數(shù)先在的寫等
9、待隊(duì)列上等待,等它被喚醒后,然后再進(jìn)行寫操作。而這一函數(shù),
最后實(shí)際上是會調(diào)用 >(, , , ); 而在此處在對應(yīng)的控制臺是時(shí), >()對應(yīng)的就是里的:
( * , , *, )
而如果對應(yīng)的是的話,那么 >() 對應(yīng)的應(yīng)該是: ()
( * , , *, )
如果對應(yīng)的是串行設(shè)備的話,那么 >()對應(yīng)的應(yīng)該是: ()
( * , *, )
或者里面的 () ;
在此處,我們以到的輸出的分析為重點(diǎn):
()
里面直接調(diào)用:
(, , , );
();
抽象的終端驅(qū)動程序?yàn)樽址K端提供了一個一般性的接口,它通過一個特別
10、的數(shù)據(jù)結(jié)構(gòu)
,里面有一些指針指向了相應(yīng)的函數(shù)來進(jìn)行進(jìn)一步操作。
* ( *)>;
定義在里面,而在里面有一個全局變量:
*[];
()
首先該過程會得到當(dāng)前的的
>;
進(jìn)入臨界區(qū)
();
開始寫屏
如果是轉(zhuǎn)義序列則進(jìn)入一個自動機(jī),進(jìn)行翻譯 ,
并根據(jù)轉(zhuǎn)義序列的進(jìn)行實(shí)際的動作。
最后寫屏
退出臨界區(qū)
();
值得注意的是其中為了識別轉(zhuǎn)義序列,使用了一個有限狀態(tài)自動機(jī):
如下圖所示:
分析轉(zhuǎn)義序列的自動機(jī)
5 / 6
11、
非 ”[“ “[“ 數(shù)字或 ”[“
( )
( )
非數(shù)字 ”;”
中用于各種顯示功能的函數(shù):
( *, *);
( , ,
, );
();
( , , );
( );
( , );
( *);
( );
( );
( );
以下略。
6 / 6