• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            T9的空間

            You will never walk alone!

              C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
              69 隨筆 :: 0 文章 :: 28 評(píng)論 :: 0 Trackbacks

            置頂隨筆 #

                 摘要: 這是在一個(gè)百度貼吧里轉(zhuǎn)載的OJ及有用的網(wǎng)址收集!  閱讀全文
            posted @ 2008-09-09 21:20 Torres 閱讀(3061) | 評(píng)論 (32)編輯 收藏

            一直想有一個(gè)blog,做做筆記,整理整理思路,基于這個(gè)思想,這個(gè)blog誕生了!以后就靠這個(gè)來(lái)祭奠生活了。
            posted @ 2008-08-11 12:30 Torres 閱讀(180) | 評(píng)論 (1)編輯 收藏

            2014年7月8日 #

            許下一個(gè)美好愿望吧,期望能在空余的時(shí)間把多年前買(mǎi)的一本書(shū)看完。
            Pushing yourself when no one else is around.
            posted @ 2014-07-08 20:11 Torres 閱讀(264) | 評(píng)論 (0)編輯 收藏

            2013年12月9日 #

            From Unix某論壇,忘記名字了...但這段文字從宏觀上講清楚了Linux Memory的構(gòu)架。
            1.
            內(nèi)核初始化:

                *
            內(nèi)核建立好內(nèi)核頁(yè)目錄頁(yè)表數(shù)據(jù)庫(kù),假設(shè)物理內(nèi)存大小為len,則建立了[3G--3G+len]::[0--len]這樣的虛地址vaddr和物理地址paddr的線(xiàn)性對(duì)應(yīng)關(guān)系;
                *
            內(nèi)核建立一個(gè)page數(shù)組,page數(shù)組和物理頁(yè)面系列完全是線(xiàn)性對(duì)應(yīng),page用來(lái)管理該物理頁(yè)面狀態(tài),每個(gè)物理頁(yè)面的虛地址保存在page->virtual中;
                *
            內(nèi)核建立好一個(gè)free_list,將沒(méi)有使用的物理頁(yè)面對(duì)應(yīng)的page放入其中,已經(jīng)使用的就不用放入了;

            2.
            內(nèi)核模塊申請(qǐng)內(nèi)存vaddr = get_free_pages(mask,order)

                *
            內(nèi)存管理模塊從free_list找到一個(gè)page,將page->virtual作為返回值,該返回值就是對(duì)應(yīng)物理頁(yè)面的虛地址;
                *
            pagefree_list中脫離;
                *
            模塊使用該虛擬地址操作對(duì)應(yīng)的物理內(nèi)存;

            3.
            內(nèi)核模塊使用vaddr,例如執(zhí)行指令mov(eax, vaddr)

                * CPU
            獲得vaddr這個(gè)虛地址,利用建立好的頁(yè)目錄頁(yè)表數(shù)據(jù)庫(kù),找到其對(duì)應(yīng)的物理內(nèi)存地址;
                *
            eax的內(nèi)容寫(xiě)入vaddr對(duì)應(yīng)的物理內(nèi)存地址內(nèi);

            4.
            內(nèi)核模塊釋放內(nèi)存free_pages(vaddr,order)

                *
            依據(jù)vaddr找到對(duì)應(yīng)的page
                *
            將該page加入到free_list中;

            5.
            用戶(hù)進(jìn)程申請(qǐng)內(nèi)存vaddr = malloc(size)

                *
            內(nèi)存管理模塊從用戶(hù)進(jìn)程內(nèi)存空間(0--3G)中找到一塊還沒(méi)使用的空間vm_area_struct(start--end)
                *
            隨后將其插入到task->mm->mmap鏈表中;

            6.
            用戶(hù)進(jìn)程寫(xiě)入vaddr(0-3G),例如執(zhí)行指令mov(eax, vaddr)

                * CPU
            獲得vaddr這個(gè)虛地址,該虛地址應(yīng)該已經(jīng)由glibc庫(kù)設(shè)置好了,一定在3G一下的某個(gè)區(qū)域,根據(jù)CR3寄存器指向的current->pgd查當(dāng)前進(jìn)程的頁(yè)目錄頁(yè)表數(shù)據(jù)庫(kù),發(fā)現(xiàn)該vaddr對(duì)應(yīng)的頁(yè)目錄表項(xiàng)為0,故產(chǎn)生異常;
                *
            在異常處理中,發(fā)現(xiàn)該vaddr對(duì)應(yīng)的vm_area_struct已經(jīng)存在,為vaddr對(duì)應(yīng)的頁(yè)目錄表項(xiàng)分配一個(gè)頁(yè)表;
                *
            隨后從free_list找到一個(gè)page,將該page對(duì)應(yīng)的物理頁(yè)面物理首地址賦給vaddr對(duì)應(yīng)的頁(yè)表表項(xiàng),很明顯,此時(shí)的vaddrpaddr不是線(xiàn)性對(duì)應(yīng)關(guān)系了;
                *
            pagefree_list中脫離;
                *
            異常處理返回;
                * CPU
            重新執(zhí)行剛剛發(fā)生異常的指令mov(eax, vaddr)
                * CPU
            獲得vaddr這個(gè)虛地址,根據(jù)CR3寄存器指向的current->pgd,利用建立好的頁(yè)目錄頁(yè)表數(shù)據(jù)庫(kù),找到其對(duì)應(yīng)的物理內(nèi)存地址;
                *
            eax的內(nèi)容寫(xiě)入vaddr對(duì)應(yīng)的物理內(nèi)存地址內(nèi);  

            7.
            用戶(hù)進(jìn)程釋放內(nèi)存vaddrfree(vaddr)

                *
            找到該vaddr所在的vm_area_struct
                *
            找到vm_area_struct:start--end對(duì)應(yīng)的所有頁(yè)目錄頁(yè)表項(xiàng),清空對(duì)應(yīng)的所有頁(yè)表項(xiàng);
                *
            釋放這些頁(yè)表項(xiàng)指向物理頁(yè)面所對(duì)應(yīng)的page,并將這些page加入到free_list隊(duì)列中;
                *
            有必要還會(huì)清空一些頁(yè)目錄表項(xiàng),并釋放這些頁(yè)目錄表項(xiàng)指向的頁(yè)表;
                *
            task->mm->mmap鏈中刪除該vm_area_struct并釋放掉;

            綜合說(shuō)明:

                *
            可用物理內(nèi)存就是free_list中各page對(duì)應(yīng)的物理內(nèi)存;
                *
            頁(yè)目錄頁(yè)表數(shù)據(jù)庫(kù)的主要目的是為CPU訪問(wèn)物理內(nèi)存時(shí)轉(zhuǎn)換vaddr-->paddr使用,分配以及釋放內(nèi)存時(shí)不會(huì)用到,但是需要內(nèi)核內(nèi)存管理系統(tǒng)在合適時(shí)機(jī)為CPU建立好該庫(kù);
                *
            對(duì)于用戶(hù)進(jìn)程在6中獲得的物理頁(yè)面,有兩個(gè)頁(yè)表項(xiàng)對(duì)應(yīng),一個(gè)就是內(nèi)核頁(yè)目錄頁(yè)表數(shù)據(jù)庫(kù)的某個(gè)pte[i ],一個(gè)就是當(dāng)前進(jìn)程內(nèi)核頁(yè)目錄頁(yè)表數(shù)據(jù)庫(kù)的某個(gè) pte[j],但是只有一個(gè)page和其對(duì)應(yīng)。如果此時(shí)調(diào)度到其他進(jìn)程,其他進(jìn)程申請(qǐng)并訪問(wèn)某個(gè)內(nèi)存,則不會(huì)涉及到該物理頁(yè)面,因?yàn)槠浞峙鋾r(shí)首先要從 free_list中找一個(gè)page,而該物理頁(yè)面對(duì)應(yīng)的page已經(jīng)從free_list中脫離出來(lái)了,因此不存在該物理頁(yè)面被其他進(jìn)程改寫(xiě)操作的情況。內(nèi)核中通過(guò)get_free_pages等方式獲取內(nèi)存時(shí),也不會(huì)涉及到該物理頁(yè)面,原理同前所述。
            posted @ 2013-12-09 17:42 Torres 閱讀(462) | 評(píng)論 (0)編輯 收藏

            from: http://www.cnblogs.com/whjiang/articles/1387364.html

            1. 盡可能不要?jiǎng)?chuàng)建global reference和global weak reference. 創(chuàng)建這兩類(lèi)引用的JNI接口NewGlobalReference和NewGlobalWeakReference內(nèi)部實(shí)現(xiàn)

            有一個(gè)鎖。這個(gè)鎖使得在多處理器上的可擴(kuò)展性非常差,因?yàn)楦鱾€(gè)線(xiàn)程都在等待這個(gè)鎖。所以盡量不要在native保存java 對(duì)象的引用,情愿在每次
            JNI call時(shí)都帶點(diǎn)參數(shù)。當(dāng)然,在native保持java對(duì)象的local reference是非常危險(xiǎn)的,絕對(duì)不能那樣干。

            2. 盡量不要使用GetPrimitiveArrayCritical/ReleasePrimitiveArrayCritical來(lái)pin住Java內(nèi)存。JVM本身沒(méi)有提供任何只pin住一塊Java內(nèi)存而不影
            響GC的操作,所以這個(gè)操作是會(huì)阻止GC進(jìn)行的。作為補(bǔ)償,ReleasePrimitiveArrayCritical會(huì)產(chǎn)生一次隱式的GC調(diào)用。這樣就可能出現(xiàn)在需要GC的時(shí)
            候無(wú)法GC,而在不需要GC時(shí)進(jìn)行無(wú)意義GC的情況。另外,這兩個(gè)操作的實(shí)現(xiàn)中在某些情況下也可能觸發(fā)鎖。解決方法:如果是小塊內(nèi)存的話(huà),情愿使
            用Get<Type>ArrayRegion和Set<Type>ArrayRegion來(lái)在native和Java之間復(fù)制內(nèi)存。

            3. 在Java appliation中盡量不要?jiǎng)?chuàng)建phantom reference或者soft reference。這些reference會(huì)極大的影響GC。
            我們先來(lái)談?wù)凧VM的GC。GC分為minor GC和full GC。Java內(nèi)存分為young和old兩代。在young memory中,每個(gè)線(xiàn)程都有自己的內(nèi)存分配塊(不和其它
            線(xiàn)程共享),而old memory是由所有線(xiàn)程共享的。minor GC只對(duì)young memory作GC,而full GC對(duì)所有內(nèi)存都做GC。minor GC是可以多線(xiàn)程并行進(jìn)行的
            ,而full GC默認(rèn)只能單線(xiàn)程執(zhí)行。所以,一次full GC需要的時(shí)間可以是minor GC是10倍以上(可以用-verbose:gc觀察)。所以在一般應(yīng)用中,
            minor GC的次數(shù)應(yīng)該是full GC的10倍左右是比較理想的。minor GC會(huì)將無(wú)法收集的對(duì)象移動(dòng)到old memory中去。

            minor GC不會(huì)對(duì)phantom reference和soft reference進(jìn)行收集,只有full GC才會(huì)。這樣的問(wèn)題就是大量的這類(lèi)對(duì)象積聚起來(lái),產(chǎn)生許多的內(nèi)存復(fù)制。

            這樣每次minor GC可能就基本上沒(méi)有釋放多少內(nèi)存,使得full GC就會(huì)被頻繁觸發(fā)。可能出現(xiàn)minor GC和full GC次數(shù)1:1的情況,甚至全是full GC。

            這樣,無(wú)論是性能還是可擴(kuò)展性都是非常差的。

            weak reference的影響好像小一些,但也應(yīng)該盡量避免。

             

            在JNI開(kāi)發(fā)中,使用這3種reference的主要目的是保證native資源的釋放。因?yàn)閖ava對(duì)象的finalize方法是不保證被調(diào)用的,所以必須用這些

            reference來(lái)幫助實(shí)現(xiàn)native資源釋放。為了避免上述的問(wèn)題,一種可行的方法是將native資源serialize成一塊內(nèi)存,然后放到j(luò)ava對(duì)象中保存,從
            而避免使用這些reference。

            4. NIO是不錯(cuò)的Java和native之間share memory的方法。但要注意它的性能。首先一定要設(shè)置對(duì)big endian還是little endian,防止JVM做額外的
            endian轉(zhuǎn)換動(dòng)作。其次是在啟動(dòng)JVM時(shí)一定要加上-server選項(xiàng),否則nio性能會(huì)非常差。在-server mode下,nio性能大概比java數(shù)組慢30%~50%.在-
            client mode下,性能差1倍以上。

            5. 盡量不要在JNI去new Java String對(duì)象。這個(gè)比在java層new慢很多。

            6. 對(duì)java大對(duì)象(比方說(shuō)數(shù)組),一定要仔細(xì)的tune他的大小。一般來(lái)說(shuō),小對(duì)象對(duì)GC比較友好。因?yàn)閷?duì)象分配時(shí)先看每個(gè)線(xiàn)程自己的young memory
            ,如果找的到足夠大的內(nèi)存的話(huà),就分配。否則在old memory中分配。因?yàn)閛ld memory是shared,所以可能有鎖開(kāi)銷(xiāo)。而且old memory中的對(duì)象只有
            full GC才能釋放它。所以對(duì)象比較小是比較好的。JVM的內(nèi)存分配算法是為小對(duì)象優(yōu)化過(guò)的,大量小對(duì)象的分配是很高效的,所以不用怕把大對(duì)象拆小。
            在某些情況下,如果知道對(duì)象會(huì)活的很久的話(huà),就讓它大一點(diǎn),增加它直接分配在old memory中的概率。這樣可以節(jié)約young GC拷貝這個(gè)對(duì)象到old 

            memory中的開(kāi)銷(xiāo)。

            posted @ 2013-12-09 17:40 Torres 閱讀(592) | 評(píng)論 (0)編輯 收藏

            2013年10月21日 #

            第二章
            編譯和鏈接
            這章比較籠統(tǒng),都是概念,熟悉基本流程的人,建議不看。
             
            記錄一些基本流程
             
            拿GCC來(lái)說(shuō)
            用GCC編譯鏈接生成可執(zhí)行文件的過(guò)程分為下面4個(gè)步驟
            Prepressing,Compilation,Assembly,Linking
             
            Prepressing 預(yù)處理
            從.c -> .i (gcc -E)
            主要是處理,前綴為‘#’的語(yǔ)句
             
            define的直接替換
            對(duì)define這種,從我觀察應(yīng)該是這樣
            對(duì)源文件類(lèi)似.c直接掃描 看到define的符號(hào)直接加到表中
            然后在替換的時(shí)候會(huì)做遞歸檢查,直到符號(hào)是最終定義。
             
            所以這個(gè)與define的順序沒(méi)有太大關(guān)系了,只要不循環(huán)嵌套
             
            類(lèi)似這種
            #define M (N + 1)
            #define N 2
             
            這種在用到M的時(shí)候,會(huì)先替換成 (N + 1)但是發(fā)現(xiàn)替換的表達(dá)式中還有未決symbol,那么
            就再進(jìn)行替換 (2 + 1)
             
            表中并不會(huì)直接寫(xiě)成 M (2 + 1),至少我看到的GCC行為是這樣。
             
            include的也是直接導(dǎo)入
             
            另外預(yù)編譯選項(xiàng) #ifdef 之類(lèi)的會(huì)處理掉,刪掉所有注釋
             
            #pragma是要被保留給編譯器的,這是編譯器選項(xiàng),例如 pragma pack是用來(lái)指定字節(jié)對(duì)齊標(biāo)準(zhǔn)的
             
            Compilation 編譯
            從 .i -> .s (gcc -S)
            現(xiàn)在的GCC版本都把預(yù)編譯和編譯做到了一個(gè)可執(zhí)行程序中 -> ccl
             
            編譯的主要過(guò)程
            掃描,語(yǔ)法分析,語(yǔ)義分析,源代碼優(yōu)化,代碼生成,目標(biāo)代碼優(yōu)化
            Source code --Scanner--> Tokens --Parser--> Syntax Tree
            --Semantic Analyzer--> Commented Syntax Tree --Source code Optimizer--> Intermediate Representation
            --Code Generator--> Target Code --Code Optimizer-->Final Target Code
             
            Assembly 匯編
            從 .s -> .o (gcc -c) -->匯編器as
             
            Linking 鏈接
            ld做的事情
            link的時(shí)候由于每個(gè)源文件都是單獨(dú)編譯,那么必須處理一些外來(lái)的symbol
            包括函數(shù)和全局變量
            posted @ 2013-10-21 17:01 Torres 閱讀(277) | 評(píng)論 (0)編輯 收藏

            2013年10月18日 #

            第一章
            印象:
            硬件PCI/ISA的架構(gòu)
            North Bridge相當(dāng)于人的心臟,連接所有高速設(shè)備,CPU ->大腦
            南橋芯片則負(fù)責(zé)低速設(shè)備連接
              
            SMP
             
            中間層 是解決很多問(wèn)題的大方向
            Any problem in computer science can be resolved by another layer of indirection
             
            CPU密集型 IO密集型
            這兩種類(lèi)型的Process,理論上優(yōu)先級(jí)高的,也就是說(shuō)最應(yīng)該先得到CPU的是IO密集型
            通俗的理解應(yīng)該是IO密集型做完事情花的CPU時(shí)間最少,然后就會(huì)等待IO設(shè)備的反應(yīng),這樣可以讓設(shè)備性能最大化
             
            Memory
            分段分頁(yè) MMU
             

            線(xiàn)程安全和線(xiàn)程模型
             

            其中線(xiàn)程安全有兩件事情要注意
            Semaphore
            Mutex
            上面這兩個(gè)可以做成全局的,并不一定是By Process的,例如POSIX pthread在
            對(duì)Mutex做attr設(shè)定的時(shí)候就可以指定為 shared process
            也就是說(shuō)一個(gè)Process可以加鎖,另外一個(gè)可以釋放他。
            另外這種Mutex必須處在共享內(nèi)存中,否則沒(méi)辦法訪問(wèn)。有親緣關(guān)系的Process可以通過(guò)mmap一個(gè)匿名映射做到
            anyway有很多方式了。
             
            Critical Section
            這個(gè)是Inter Process的東西。
             
            關(guān)于線(xiàn)程互斥的lock的問(wèn)題
            RW lock就是對(duì)普通lock記錄兩個(gè)狀態(tài)來(lái)供read or write操作選擇
             
            屬于線(xiàn)程本身的東西 TLS/Stack/Register
             
            有時(shí)候編譯器會(huì)為了做優(yōu)化
            內(nèi)存和寄存器的數(shù)據(jù)會(huì)出現(xiàn)不sync的狀態(tài)。
            即使你用lock來(lái)做保護(hù),也不一定能OK。然后volatile就出現(xiàn)了。 
             
            volatile最主要的作用就是thread內(nèi)保證編譯器不要做優(yōu)化,防止這種不sync帶來(lái)的問(wèn)題。
            一般是這樣例如x變量,thread_1讀到x變量放到了寄存器中,因?yàn)榭赡荞R上會(huì)再訪問(wèn)它,那么對(duì)x進(jìn)行操作后就不會(huì)寫(xiě)回內(nèi)存
            這樣即使你加了lock,這個(gè)時(shí)候lock也被釋放掉了(操作完成),但是結(jié)果未能Sync,那么thread 2來(lái)訪問(wèn)x的時(shí)候,在內(nèi)存
            中拿到的值就變成dirty狀態(tài)了。
             
            另外一種過(guò)度優(yōu)化就是CPU做的優(yōu)化,有些上下語(yǔ)義無(wú)關(guān)的指令,CPU有可能會(huì)調(diào)整運(yùn)行順序。
            書(shū)中有個(gè)經(jīng)典樣例
            一段 Singleton pattern的double-check的代碼
            volatile T* pInst = NULL;
            T* getInstance()
            {
            if (pInst == NULL)
            {
            lock();
            if (pInst == NULL)
            pInst = new T();
            unlock();
            }
            return pInst;
            }

             
            這里有兩點(diǎn)
            第一,double-check 也就是雙if能避免過(guò)多的無(wú)用的get lock,降低消耗
            對(duì)臨界區(qū)需要做保護(hù)的資源,可以提前去取狀態(tài),如果符合自己的預(yù)期,而且短時(shí)間不會(huì)有變化,那么就不用去拿鎖了
            不知道為啥我想到了unlikely,但仔細(xì)想一下,功能完全不同。
             
            第二點(diǎn)也就是要說(shuō)的CPU的過(guò)度優(yōu)化
            這里已經(jīng)是聲明volatile了,所以沒(méi)有寄存器和內(nèi)存不sync的問(wèn)題
            但是由于這里new需要先 malloc出空間,然后call T的constructor。
            所以有可能會(huì)發(fā)生這種情況,malloc出空間后,把地址付給pInst,然后去做初始化;
            這樣就有可能另外一個(gè)線(xiàn)程取得的object是沒(méi)有被完全初始化好的,是否會(huì)出問(wèn)題depend on T的具體實(shí)現(xiàn)了。
            許多CPU提供了barrier指令用來(lái)解決上面提到的問(wèn)題。
             
            線(xiàn)程模型
            這個(gè)東西,我看了下,開(kāi)始沒(méi)看明白,這邊書(shū)這個(gè)東西沒(méi)講清楚,后來(lái)去網(wǎng)上找了些資料。用戶(hù)線(xiàn)程和內(nèi)核線(xiàn)程的對(duì)應(yīng)關(guān)系取決于調(diào)度單位。
            也就是說(shuō)內(nèi)核把什么東西當(dāng)做一個(gè)調(diào)度單位
             
            拿Linux來(lái)說(shuō)吧,Process是線(xiàn)程集和資源集
             
            調(diào)度的時(shí)候,那些共享資源的Task(thread)之間的調(diào)度肯定比那些跨Process不共享資源的thread做context switch消耗的資源
            多得多。
             
            基于調(diào)度消耗之類(lèi)的考量
            模型分為下面幾種
             
            一對(duì)一,也就是說(shuō) user space create出來(lái)的線(xiàn)程就是和kernel的調(diào)度單位相同,稱(chēng)一一對(duì)應(yīng)
             
            一對(duì)多,應(yīng)該是這樣一種情況,kernel看到的是Process,userspace自己實(shí)現(xiàn)出來(lái)自己的thread,這個(gè)thread,kernel是不知道的
            調(diào)度的時(shí)候kernel負(fù)責(zé)分批CPU給他能看到的Process,上層userspace自己來(lái)調(diào)度分配這個(gè)Process獲得的CPU time給這個(gè)process中的
            各個(gè)線(xiàn)程。
            這樣的分配就可以保證在一定的時(shí)間內(nèi)只需要做一些register和stack的切換,不會(huì)有memory等等的switch。
            壞處是上面的thread只要一個(gè)被suspend,那么這個(gè)Process里面的其他thread也就被suspend住了,一般上層調(diào)度程序
            不會(huì)假定其他的thread能run,所以一般會(huì)是kernel把CPU time給其他process
             
            多對(duì)多,就是一種混合的情況了,我想到了Android,但是Android是一對(duì)一模型,dalvik會(huì)保證Java thread對(duì)應(yīng)下面一個(gè)
            native thread,想說(shuō)的是,這種虛擬機(jī)架構(gòu)可以做成多對(duì)多的樣子,一個(gè)native thread run一個(gè)JVM,JVM開(kāi)出來(lái)很多Java Thread,
            JVM負(fù)責(zé)調(diào)度這些Java Thread,Native負(fù)責(zé)調(diào)度JVM所在的Thread。
            不知道我有沒(méi)有講錯(cuò)。

            posted @ 2013-10-18 19:42 Torres 閱讀(280) | 評(píng)論 (0)編輯 收藏

            2013年10月14日 #

                 之前就翻過(guò)一次,這次再看看,期望這次能讀到我想知道的東西...
                 這個(gè)書(shū)的名字我自己覺(jué)得有點(diǎn)屌絲風(fēng)格了,Orz,期望編者勿怪
            posted @ 2013-10-14 17:07 Torres 閱讀(244) | 評(píng)論 (0)編輯 收藏

            2013年6月7日 #

            偽終端.

            這個(gè)是Muxd一直用的東西
            相當(dāng)于一個(gè)雙向PIPE
            Process A open ptm得到fdm,然后fork出process B,process B open pts得到fds,然后將0,1,2都dup到fds上
            那么fds就變成了process B的控制終端
            后面再process B中做標(biāo)準(zhǔn)IO操作的時(shí)候就會(huì)像PIPE直接影響到fdm
            終端行規(guī)程在pts之上

            沒(méi)什么特別要記錄的,在網(wǎng)上search了下,貼個(gè)鏈接,里面會(huì)介紹一些基本概念.
            http://www.cnblogs.com/Anker/archive/2012/12/25/2832568.html

            posted @ 2013-06-07 18:52 Torres 閱讀(252) | 評(píng)論 (0)編輯 收藏

            終端IO
            每個(gè)終端都有輸入輸出隊(duì)列
            隊(duì)列都有長(zhǎng)度,如果輸入超過(guò)輸入隊(duì)列MAX_INPUT長(zhǎng)度,大多數(shù)unix系統(tǒng)會(huì)回顯響鈴來(lái)處理。
            但是對(duì)于輸出隊(duì)列來(lái)講,雖然輸出隊(duì)列也有長(zhǎng)度,但是一旦寫(xiě)不進(jìn)去的時(shí)候,寫(xiě)進(jìn)程會(huì)suspend掉
            直至有空閑空間

            終端行規(guī)程 terminal line discipline
            會(huì)幫忙做規(guī)范處理

            終端設(shè)備屬性 ->termios

            struct termios {
             tcflag_t c_iflag;
             tcflag_t c_oflag;
             tcflag_t c_cflag;
             tcflag_t c_lflag;
             cc_t c_line;
             cc_t c_cc[NCCS];
            };

            local flag影響驅(qū)動(dòng)程序和用戶(hù)之間的接口
            Android上tcflag_t->
            typedef unsigned int tcflag_t;

            cc_t
            typedef unsigned char cc_t;

            control flag中很多選項(xiàng)標(biāo)志都是用幾位標(biāo)識(shí)然后用或來(lái)做選擇

            isatty的實(shí)現(xiàn),借助tcgetattr的出錯(cuò)機(jī)制,成功返回0;否則返回-1,帶上ENOTTY

            int
            isatty (int  fd)
            {
              struct termios term;

              return tcgetattr (fd, &term) == 0;
            }

            Anyway,終端IO很復(fù)雜...

            posted @ 2013-06-07 14:40 Torres 閱讀(284) | 評(píng)論 (0)編輯 收藏

            2013年6月6日 #

            IPC

            首先講到的是PIPE,這個(gè)并不陌生,相互通信的Process必須具有關(guān)系,一般是同父親的
            然后講到了協(xié)同進(jìn)程
            基本是說(shuō)有一個(gè)進(jìn)程專(zhuān)門(mén)用來(lái)接收輸入,然后處理,然后返回結(jié)果
            這個(gè)就可以用PIPE來(lái)實(shí)現(xiàn)

            創(chuàng)建兩個(gè)PIPE,一個(gè)用于輸入給協(xié)同進(jìn)程,另外一個(gè)用于接收協(xié)同進(jìn)程的輸出
            fork之后在子進(jìn)程中將標(biāo)準(zhǔn)輸入輸出都dup到管道上

            而協(xié)同進(jìn)程的寫(xiě)法可以比較common,只用關(guān)心標(biāo)準(zhǔn)輸入輸出。
            PIPE在寫(xiě)的時(shí)候如果有多個(gè)寫(xiě)進(jìn)程,那么寫(xiě)的數(shù)據(jù)小于 PIPE_BUF 則不會(huì)亂序,否則自己應(yīng)該就需要做同步了。

            然后就是FIFO,這個(gè)就是用mkfifo創(chuàng)建一個(gè)file,大家都去用。
            PIPE和FIFO都是半雙工的

            XSI IPC ->即之前System V IPC
            消息隊(duì)列 信號(hào)量 共享存儲(chǔ)器

            在無(wú)關(guān)進(jìn)程之間共享存儲(chǔ)段,一個(gè)是使用上面V系統(tǒng)shm;另外一個(gè)是使用mmap將同一文件map到他們自己的進(jìn)程空間。

            另外就是網(wǎng)絡(luò)IPC了
            算是復(fù)習(xí)下吧,之前這塊兒看的比較多
            int socket(int domain, int type, int protocol)
            domain標(biāo)識(shí)address family -> AF_INET, AF_INET6, AF_UNIX(AF_LOCAL), AF_UNSPEC
            type標(biāo)識(shí)socket類(lèi)型 -> SOCK_DGRAM(UDP), SOCK_RAW(IP), SOCK_SEQPACKET, SOCK_STREAM(TCP)

            一般protocol都設(shè)置為0,一般address family和type就能確認(rèn)要使用的protocol

            SOCK_SEQPACKET和SOCK)STREAM很像,前一個(gè)提供面向數(shù)據(jù)報(bào)文的服務(wù),而后面這種則是面對(duì)流。
            SOCK_SEQPACKET使用場(chǎng)景SCTP,貼一個(gè)SCTP的簡(jiǎn)要介紹。
            http://www.cnblogs.com/qlee/archive/2011/07/13/2105717.html

            涉及網(wǎng)絡(luò)就必須要清楚字節(jié)序的問(wèn)題,字節(jié)序與字符編碼是兩件不同的事情,都要想清楚的,但是要提一下UTF-8這是一種專(zhuān)門(mén)設(shè)計(jì)用來(lái)做網(wǎng)絡(luò)傳輸?shù)淖址幋a
            無(wú)需關(guān)心字節(jié)序的問(wèn)題,所以傳輸?shù)纳蠈訑?shù)據(jù)可以用UTF-8,就不用擔(dān)心local host和remote host的主機(jī)字節(jié)序不一樣而導(dǎo)致亂序了。

            但是很多協(xié)議頭必須做符合TCP/IP協(xié)議的字節(jié)序規(guī)范,TCP/IP是big endian
            關(guān)于Big endian和Litter endian我比較容易忘記具體的樣子,但是他的出發(fā)點(diǎn)是低地址,低地址裝的是最高有效字節(jié)那么就是big endian,否則就是litter endian。

            關(guān)于socket有幾個(gè)可能比較模糊的地方
            connect時(shí),也就是client端,如果fd沒(méi)有綁定到某個(gè)地址,那么kernel會(huì)幫忙將其綁定到默認(rèn)地址; 所以bind這件事情是Client和Server都需要做的事情,調(diào)用listen之前也一樣
            然后accept的時(shí)候,如果你關(guān)心對(duì)方的地址,那么提供addr(足夠)和len,返回的時(shí)候就能知道。
            另外UDP(SOCK_DGRAM)也可以Call connect,之后就可以直接call send/write,而不必每次都call sendto指定對(duì)端地址。

            sendto中flag一般給0,如果是緊急數(shù)據(jù)給MSG_OOB

            文件描述符的傳輸,目的是想讓不同的process在不同的文件描述符中共享文件表。
            所以做法上系統(tǒng)會(huì)這樣,傳輸文件表指針然后放到接收端的第一個(gè)可用的文件描述符上。
            這個(gè)我在linux上沒(méi)找到實(shí)現(xiàn),因?yàn)檫@個(gè)功能還是有蠻多替代方案的。

            posted @ 2013-06-06 17:22 Torres 閱讀(269) | 評(píng)論 (0)編輯 收藏

            2013年6月5日 #

            13章在講Daemon Process,沒(méi)什么特別好寫(xiě)的。
            14 ->高級(jí)IO

            低速系統(tǒng)調(diào)用,也就是有信號(hào)發(fā)生會(huì)返回 errno 為 EINTR的

            磁盤(pán)文件IO雖然有延時(shí),但是這個(gè)不能算是低速系統(tǒng)調(diào)用

            APUE介紹的低速系統(tǒng)調(diào)用
            PIPE,終端設(shè)備,網(wǎng)絡(luò)設(shè)備 讀寫(xiě)
            讀無(wú)數(shù)據(jù)/寫(xiě)無(wú)空間(例如TCP卡Congestion window)

            打開(kāi)某些特殊文件
            加記錄鎖的文件讀寫(xiě)
            ioctl,IPC


            文件鎖又叫做 byte-range locking,針對(duì)特定的文件區(qū)域,適合數(shù)據(jù)庫(kù)文件
            Posix標(biāo)準(zhǔn)
            int fcntl(int fd, int cmd, .../* struct flock* flockptr */)
            cmd -> F_GETLK,F_SETLK,F_SETLKW
            F_SETLKW是F_SETLK的Blocking版本 W means wait

            重要數(shù)據(jù)結(jié)構(gòu)是struct flock ->
            struct flock {
             short l_type;
             short l_whence;
             off_t l_start;
             off_t l_len;
             pid_t l_pid;
             __ARCH_FLOCK_PAD
            };

            鎖定整個(gè)file的方式: l_whence = SEEK_SET, l_start = 0, l_len = 0

            l_type的兩類(lèi)lock
            F_RDLCK,F(xiàn)_WRLCK這兩種鎖的特性很像rw lock

            不過(guò)與讀寫(xiě)鎖不一樣的是或者這樣講
            Posix.1沒(méi)有規(guī)定下面這種情況: process A在某文件區(qū)間上設(shè)置了一把讀鎖;process B嘗試在這個(gè)文件區(qū)間加上寫(xiě)鎖的時(shí)候suspend;process C再?lài)L試獲取讀鎖,如果允許

            process C拿到讀鎖,那么process B將會(huì)可能永遠(yuǎn)拿不到寫(xiě)鎖,活活餓死

            pthread里面的rw lock的實(shí)現(xiàn)會(huì)在這種情況下suspend掉process C的讀鎖請(qǐng)求;但是目前文件區(qū)域鎖的實(shí)現(xiàn)我不太確定

            這里看文件區(qū)域鎖還是比較容易帶來(lái)deadlock的
            例如process A鎖住F1的某個(gè)區(qū)域,然后去鎖F2的一個(gè)區(qū)域,這時(shí)候F2的這個(gè)區(qū)域被process B鎖住,那么process A就會(huì)suspend,如果這個(gè)時(shí)候process B過(guò)來(lái)要鎖F1的這個(gè)區(qū)域
            就會(huì)發(fā)生deadlock


            關(guān)于文件區(qū)域鎖的繼承和釋放
            1.fork后,文件區(qū)域鎖并不繼承,繼承了就完了,不同的process就有可能同時(shí)干同一件事情,把數(shù)據(jù)搞壞
            2.close(fd)后 fd對(duì)應(yīng)的文件鎖就被釋放了,文件鎖掛在inode上,close的時(shí)候kernel會(huì)去掃描對(duì)應(yīng)的inode上與這個(gè)PID相關(guān)的lock,釋放掉,而并不去關(guān)心是哪個(gè)文件描述符或

            者是哪個(gè)文件表,這很重要,因?yàn)閘ockf中并不記錄fd,他們只是弱關(guān)聯(lián)關(guān)系,這個(gè)很重要。
            3.exec后,文件鎖會(huì)繼承原來(lái)執(zhí)行程序的鎖(fork之后拿到的lock),如果fd帶有close-on-exec那么根據(jù)第二條,這個(gè)fd對(duì)應(yīng)的file上的鎖都會(huì)被釋放。


            后面講了STREAMS,感覺(jué)linux上用到的不多,需要在編譯kernel時(shí)動(dòng)態(tài)加載

            IO多路轉(zhuǎn)接,主要是為了實(shí)現(xiàn)polling既所謂的輪詢(xún)
            主要函數(shù)有select,pselect,poll,epoll
            select也會(huì)算是低速系統(tǒng)調(diào)用,那么就有可能被信號(hào)打斷
            pselect有參數(shù)可以設(shè)定信號(hào)屏蔽集,也提供更高精度的timer

            poll的方式與select有不太一樣的地方,但是功能相同,epoll更適合大數(shù)據(jù)量。

            readv和writev
            記住下面兩條就夠了
            一個(gè)稱(chēng)為scatter read(散步讀);另外一個(gè)稱(chēng)為gather write(聚集寫(xiě))
            這兩個(gè)函數(shù)會(huì)面對(duì)一個(gè)buffer鏈表。


            readn和writen
            這個(gè)比較像現(xiàn)在Android里面socket的read和write方式,保證能read/write n byte數(shù)據(jù),在內(nèi)部做循環(huán)
            我比較好奇這兩個(gè)是否會(huì)處理signal,想來(lái)應(yīng)該是會(huì)處理的,遇到EINTR幫忙重啟就好了

            我沒(méi)有找到Bionic庫(kù)的實(shí)現(xiàn)


            存儲(chǔ)映射IO
            這個(gè)很重要,mmap用的很多,映射到process空間的位置在 stack以下,heap以上的部分,map完后返回低地址。

            #include<sys/mman.h>
            void* mmap(void* addr, size_t len, int prot, int flag, int filedes, off_t off)

            prot -> PROT_READ,PROT_WRITE,PROT_EXEC,PROT_NONE
            prot指定的對(duì)映射存儲(chǔ)區(qū)的保護(hù)不能超過(guò)文件的open權(quán)限

            在 flag為 MAP_FIXED的時(shí)候OS會(huì)保證分配的memory起始地址為addr,否則只是給OS一個(gè)建議。
            一般建議addr給0,讓OS來(lái)決定。

            MAP_SHARED是說(shuō)對(duì)映射區(qū)域的存儲(chǔ)(write)會(huì)導(dǎo)致修改該文件。
            MAP_PRIVATE則是對(duì)映射區(qū)域的操作會(huì)常見(jiàn)一個(gè)映射文件的副本。


            后面有個(gè)例子用了lseek
            使用lseek增加文件長(zhǎng)度的方式,先lseek一個(gè)值,如果這個(gè)值大于文件本身的長(zhǎng)度,那么下一次寫(xiě)就會(huì)加長(zhǎng)該文件,并且在文件
            中形成一個(gè)空洞,未寫(xiě)過(guò)的內(nèi)容全部讀為0。
            mmap只能map文件的最大長(zhǎng)度,超過(guò)的地方?jīng)]辦法同步到文件。

            posted @ 2013-06-05 16:59 Torres 閱讀(322) | 評(píng)論 (0)編輯 收藏

            僅列出標(biāo)題  下一頁(yè)
            国产精品VIDEOSSEX久久发布| 人妻精品久久久久中文字幕| 伊人久久大香线蕉无码麻豆| 26uuu久久五月天| 精品久久久久久国产| 97久久超碰成人精品网站| 久久精品99久久香蕉国产色戒 | 久久综合给合久久狠狠狠97色| 欧美久久一区二区三区| 激情综合色综合久久综合| 亚洲天堂久久精品| 精品国产青草久久久久福利| 国产成人综合久久精品尤物| 久久久精品视频免费观看| 久久青青草原亚洲av无码| 中文字幕无码久久久| 亚洲欧洲久久久精品| 一本色道久久综合亚洲精品| 久久精品国产亚洲AV大全| 久久精品国产99国产精偷| 九九热久久免费视频| 久久无码国产| 亚洲精品乱码久久久久久中文字幕| 伊人久久综合成人网| 国产韩国精品一区二区三区久久| 欧美精品一本久久男人的天堂| 99久久人人爽亚洲精品美女| 日本久久中文字幕| 久久久精品人妻一区二区三区四| 精品九九久久国内精品| 日韩十八禁一区二区久久| 成人久久免费网站| 日本福利片国产午夜久久| 色婷婷综合久久久久中文字幕 | 国产综合久久久久| 国产高潮国产高潮久久久91 | 91久久精品无码一区二区毛片| 久久这里只有精品视频99| 无码AV波多野结衣久久| 国产69精品久久久久9999| 国产A三级久久精品|