• <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++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
              69 隨筆 :: 0 文章 :: 28 評論 :: 0 Trackbacks

            置頂隨筆 #

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

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

            2014年7月8日 #

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

            2013年12月9日 #

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

                *
            內核建立好內核頁目錄頁表數據庫,假設物理內存大小為len,則建立了[3G--3G+len]::[0--len]這樣的虛地址vaddr和物理地址paddr的線性對應關系;
                *
            內核建立一個page數組,page數組和物理頁面系列完全是線性對應,page用來管理該物理頁面狀態,每個物理頁面的虛地址保存在page->virtual中;
                *
            內核建立好一個free_list,將沒有使用的物理頁面對應的page放入其中,已經使用的就不用放入了;

            2.
            內核模塊申請內存vaddr = get_free_pages(mask,order)

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

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

                * CPU
            獲得vaddr這個虛地址,利用建立好的頁目錄頁表數據庫,找到其對應的物理內存地址;
                *
            eax的內容寫入vaddr對應的物理內存地址內;

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

                *
            依據vaddr找到對應的page
                *
            將該page加入到free_list中;

            5.
            用戶進程申請內存vaddr = malloc(size)

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

            6.
            用戶進程寫入vaddr(0-3G),例如執行指令mov(eax, vaddr)

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

            7.
            用戶進程釋放內存vaddrfree(vaddr)

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

            綜合說明:

                *
            可用物理內存就是free_list中各page對應的物理內存;
                *
            頁目錄頁表數據庫的主要目的是為CPU訪問物理內存時轉換vaddr-->paddr使用,分配以及釋放內存時不會用到,但是需要內核內存管理系統在合適時機為CPU建立好該庫;
                *
            對于用戶進程在6中獲得的物理頁面,有兩個頁表項對應,一個就是內核頁目錄頁表數據庫的某個pte[i ],一個就是當前進程內核頁目錄頁表數據庫的某個 pte[j],但是只有一個page和其對應。如果此時調度到其他進程,其他進程申請并訪問某個內存,則不會涉及到該物理頁面,因為其分配時首先要從 free_list中找一個page,而該物理頁面對應的page已經從free_list中脫離出來了,因此不存在該物理頁面被其他進程改寫操作的情況。內核中通過get_free_pages等方式獲取內存時,也不會涉及到該物理頁面,原理同前所述。
            posted @ 2013-12-09 17:42 Torres 閱讀(462) | 評論 (0)編輯 收藏

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

            1. 盡可能不要創建global reference和global weak reference. 創建這兩類引用的JNI接口NewGlobalReference和NewGlobalWeakReference內部實現

            有一個鎖。這個鎖使得在多處理器上的可擴展性非常差,因為各個線程都在等待這個鎖。所以盡量不要在native保存java 對象的引用,情愿在每次
            JNI call時都帶點參數。當然,在native保持java對象的local reference是非常危險的,絕對不能那樣干。

            2. 盡量不要使用GetPrimitiveArrayCritical/ReleasePrimitiveArrayCritical來pin住Java內存。JVM本身沒有提供任何只pin住一塊Java內存而不影
            響GC的操作,所以這個操作是會阻止GC進行的。作為補償,ReleasePrimitiveArrayCritical會產生一次隱式的GC調用。這樣就可能出現在需要GC的時
            候無法GC,而在不需要GC時進行無意義GC的情況。另外,這兩個操作的實現中在某些情況下也可能觸發鎖。解決方法:如果是小塊內存的話,情愿使
            用Get<Type>ArrayRegion和Set<Type>ArrayRegion來在native和Java之間復制內存。

            3. 在Java appliation中盡量不要創建phantom reference或者soft reference。這些reference會極大的影響GC。
            我們先來談談JVM的GC。GC分為minor GC和full GC。Java內存分為young和old兩代。在young memory中,每個線程都有自己的內存分配塊(不和其它
            線程共享),而old memory是由所有線程共享的。minor GC只對young memory作GC,而full GC對所有內存都做GC。minor GC是可以多線程并行進行的
            ,而full GC默認只能單線程執行。所以,一次full GC需要的時間可以是minor GC是10倍以上(可以用-verbose:gc觀察)。所以在一般應用中,
            minor GC的次數應該是full GC的10倍左右是比較理想的。minor GC會將無法收集的對象移動到old memory中去。

            minor GC不會對phantom reference和soft reference進行收集,只有full GC才會。這樣的問題就是大量的這類對象積聚起來,產生許多的內存復制。

            這樣每次minor GC可能就基本上沒有釋放多少內存,使得full GC就會被頻繁觸發。可能出現minor GC和full GC次數1:1的情況,甚至全是full GC。

            這樣,無論是性能還是可擴展性都是非常差的。

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

             

            在JNI開發中,使用這3種reference的主要目的是保證native資源的釋放。因為java對象的finalize方法是不保證被調用的,所以必須用這些

            reference來幫助實現native資源釋放。為了避免上述的問題,一種可行的方法是將native資源serialize成一塊內存,然后放到java對象中保存,從
            而避免使用這些reference。

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

            5. 盡量不要在JNI去new Java String對象。這個比在java層new慢很多。

            6. 對java大對象(比方說數組),一定要仔細的tune他的大小。一般來說,小對象對GC比較友好。因為對象分配時先看每個線程自己的young memory
            ,如果找的到足夠大的內存的話,就分配。否則在old memory中分配。因為old memory是shared,所以可能有鎖開銷。而且old memory中的對象只有
            full GC才能釋放它。所以對象比較小是比較好的。JVM的內存分配算法是為小對象優化過的,大量小對象的分配是很高效的,所以不用怕把大對象拆小。
            在某些情況下,如果知道對象會活的很久的話,就讓它大一點,增加它直接分配在old memory中的概率。這樣可以節約young GC拷貝這個對象到old 

            memory中的開銷。

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

            2013年10月21日 #

            第二章
            編譯和鏈接
            這章比較籠統,都是概念,熟悉基本流程的人,建議不看。
             
            記錄一些基本流程
             
            拿GCC來說
            用GCC編譯鏈接生成可執行文件的過程分為下面4個步驟
            Prepressing,Compilation,Assembly,Linking
             
            Prepressing 預處理
            從.c -> .i (gcc -E)
            主要是處理,前綴為‘#’的語句
             
            define的直接替換
            對define這種,從我觀察應該是這樣
            對源文件類似.c直接掃描 看到define的符號直接加到表中
            然后在替換的時候會做遞歸檢查,直到符號是最終定義。
             
            所以這個與define的順序沒有太大關系了,只要不循環嵌套
             
            類似這種
            #define M (N + 1)
            #define N 2
             
            這種在用到M的時候,會先替換成 (N + 1)但是發現替換的表達式中還有未決symbol,那么
            就再進行替換 (2 + 1)
             
            表中并不會直接寫成 M (2 + 1),至少我看到的GCC行為是這樣。
             
            include的也是直接導入
             
            另外預編譯選項 #ifdef 之類的會處理掉,刪掉所有注釋
             
            #pragma是要被保留給編譯器的,這是編譯器選項,例如 pragma pack是用來指定字節對齊標準的
             
            Compilation 編譯
            從 .i -> .s (gcc -S)
            現在的GCC版本都把預編譯和編譯做到了一個可執行程序中 -> ccl
             
            編譯的主要過程
            掃描,語法分析,語義分析,源代碼優化,代碼生成,目標代碼優化
            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的時候由于每個源文件都是單獨編譯,那么必須處理一些外來的symbol
            包括函數和全局變量
            posted @ 2013-10-21 17:01 Torres 閱讀(277) | 評論 (0)編輯 收藏

            2013年10月18日 #

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

            線程安全和線程模型
             

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

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

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

            2013年10月14日 #

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

            2013年6月7日 #

            偽終端.

            這個是Muxd一直用的東西
            相當于一個雙向PIPE
            Process A open ptm得到fdm,然后fork出process B,process B open pts得到fds,然后將0,1,2都dup到fds上
            那么fds就變成了process B的控制終端
            后面再process B中做標準IO操作的時候就會像PIPE直接影響到fdm
            終端行規程在pts之上

            沒什么特別要記錄的,在網上search了下,貼個鏈接,里面會介紹一些基本概念.
            http://www.cnblogs.com/Anker/archive/2012/12/25/2832568.html

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

            終端IO
            每個終端都有輸入輸出隊列
            隊列都有長度,如果輸入超過輸入隊列MAX_INPUT長度,大多數unix系統會回顯響鈴來處理。
            但是對于輸出隊列來講,雖然輸出隊列也有長度,但是一旦寫不進去的時候,寫進程會suspend掉
            直至有空閑空間

            終端行規程 terminal line discipline
            會幫忙做規范處理

            終端設備屬性 ->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影響驅動程序和用戶之間的接口
            Android上tcflag_t->
            typedef unsigned int tcflag_t;

            cc_t
            typedef unsigned char cc_t;

            control flag中很多選項標志都是用幾位標識然后用或來做選擇

            isatty的實現,借助tcgetattr的出錯機制,成功返回0;否則返回-1,帶上ENOTTY

            int
            isatty (int  fd)
            {
              struct termios term;

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

            Anyway,終端IO很復雜...

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

            2013年6月6日 #

            IPC

            首先講到的是PIPE,這個并不陌生,相互通信的Process必須具有關系,一般是同父親的
            然后講到了協同進程
            基本是說有一個進程專門用來接收輸入,然后處理,然后返回結果
            這個就可以用PIPE來實現

            創建兩個PIPE,一個用于輸入給協同進程,另外一個用于接收協同進程的輸出
            fork之后在子進程中將標準輸入輸出都dup到管道上

            而協同進程的寫法可以比較common,只用關心標準輸入輸出。
            PIPE在寫的時候如果有多個寫進程,那么寫的數據小于 PIPE_BUF 則不會亂序,否則自己應該就需要做同步了。

            然后就是FIFO,這個就是用mkfifo創建一個file,大家都去用。
            PIPE和FIFO都是半雙工的

            XSI IPC ->即之前System V IPC
            消息隊列 信號量 共享存儲器

            在無關進程之間共享存儲段,一個是使用上面V系統shm;另外一個是使用mmap將同一文件map到他們自己的進程空間。

            另外就是網絡IPC了
            算是復習下吧,之前這塊兒看的比較多
            int socket(int domain, int type, int protocol)
            domain標識address family -> AF_INET, AF_INET6, AF_UNIX(AF_LOCAL), AF_UNSPEC
            type標識socket類型 -> SOCK_DGRAM(UDP), SOCK_RAW(IP), SOCK_SEQPACKET, SOCK_STREAM(TCP)

            一般protocol都設置為0,一般address family和type就能確認要使用的protocol

            SOCK_SEQPACKET和SOCK)STREAM很像,前一個提供面向數據報文的服務,而后面這種則是面對流。
            SOCK_SEQPACKET使用場景SCTP,貼一個SCTP的簡要介紹。
            http://www.cnblogs.com/qlee/archive/2011/07/13/2105717.html

            涉及網絡就必須要清楚字節序的問題,字節序與字符編碼是兩件不同的事情,都要想清楚的,但是要提一下UTF-8這是一種專門設計用來做網絡傳輸的字符編碼
            無需關心字節序的問題,所以傳輸的上層數據可以用UTF-8,就不用擔心local host和remote host的主機字節序不一樣而導致亂序了。

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

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

            sendto中flag一般給0,如果是緊急數據給MSG_OOB

            文件描述符的傳輸,目的是想讓不同的process在不同的文件描述符中共享文件表。
            所以做法上系統會這樣,傳輸文件表指針然后放到接收端的第一個可用的文件描述符上。
            這個我在linux上沒找到實現,因為這個功能還是有蠻多替代方案的。

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

            2013年6月5日 #

            13章在講Daemon Process,沒什么特別好寫的。
            14 ->高級IO

            低速系統調用,也就是有信號發生會返回 errno 為 EINTR的

            磁盤文件IO雖然有延時,但是這個不能算是低速系統調用

            APUE介紹的低速系統調用
            PIPE,終端設備,網絡設備 讀寫
            讀無數據/寫無空間(例如TCP卡Congestion window)

            打開某些特殊文件
            加記錄鎖的文件讀寫
            ioctl,IPC


            文件鎖又叫做 byte-range locking,針對特定的文件區域,適合數據庫文件
            Posix標準
            int fcntl(int fd, int cmd, .../* struct flock* flockptr */)
            cmd -> F_GETLK,F_SETLK,F_SETLKW
            F_SETLKW是F_SETLK的Blocking版本 W means wait

            重要數據結構是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
            };

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

            l_type的兩類lock
            F_RDLCK,F_WRLCK這兩種鎖的特性很像rw lock

            不過與讀寫鎖不一樣的是或者這樣講
            Posix.1沒有規定下面這種情況: process A在某文件區間上設置了一把讀鎖;process B嘗試在這個文件區間加上寫鎖的時候suspend;process C再嘗試獲取讀鎖,如果允許

            process C拿到讀鎖,那么process B將會可能永遠拿不到寫鎖,活活餓死

            pthread里面的rw lock的實現會在這種情況下suspend掉process C的讀鎖請求;但是目前文件區域鎖的實現我不太確定

            這里看文件區域鎖還是比較容易帶來deadlock的
            例如process A鎖住F1的某個區域,然后去鎖F2的一個區域,這時候F2的這個區域被process B鎖住,那么process A就會suspend,如果這個時候process B過來要鎖F1的這個區域
            就會發生deadlock


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

            者是哪個文件表,這很重要,因為lockf中并不記錄fd,他們只是弱關聯關系,這個很重要。
            3.exec后,文件鎖會繼承原來執行程序的鎖(fork之后拿到的lock),如果fd帶有close-on-exec那么根據第二條,這個fd對應的file上的鎖都會被釋放。


            后面講了STREAMS,感覺linux上用到的不多,需要在編譯kernel時動態加載

            IO多路轉接,主要是為了實現polling既所謂的輪詢
            主要函數有select,pselect,poll,epoll
            select也會算是低速系統調用,那么就有可能被信號打斷
            pselect有參數可以設定信號屏蔽集,也提供更高精度的timer

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

            readv和writev
            記住下面兩條就夠了
            一個稱為scatter read(散步讀);另外一個稱為gather write(聚集寫)
            這兩個函數會面對一個buffer鏈表。


            readn和writen
            這個比較像現在Android里面socket的read和write方式,保證能read/write n byte數據,在內部做循環
            我比較好奇這兩個是否會處理signal,想來應該是會處理的,遇到EINTR幫忙重啟就好了

            我沒有找到Bionic庫的實現


            存儲映射IO
            這個很重要,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指定的對映射存儲區的保護不能超過文件的open權限

            在 flag為 MAP_FIXED的時候OS會保證分配的memory起始地址為addr,否則只是給OS一個建議。
            一般建議addr給0,讓OS來決定。

            MAP_SHARED是說對映射區域的存儲(write)會導致修改該文件。
            MAP_PRIVATE則是對映射區域的操作會常見一個映射文件的副本。


            后面有個例子用了lseek
            使用lseek增加文件長度的方式,先lseek一個值,如果這個值大于文件本身的長度,那么下一次寫就會加長該文件,并且在文件
            中形成一個空洞,未寫過的內容全部讀為0。
            mmap只能map文件的最大長度,超過的地方沒辦法同步到文件。

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

            僅列出標題  下一頁
            久久男人Av资源网站无码软件| 精品久久久久久国产| 精品国产VA久久久久久久冰| 无码人妻久久一区二区三区免费丨 | 免费精品久久久久久中文字幕| 国产午夜电影久久| 中文精品99久久国产 | AAA级久久久精品无码片| 国产成人精品久久二区二区| 久久久久久亚洲精品无码| 伊人久久大香线蕉亚洲五月天| 久久精品成人免费看| 久久人人爽人人人人爽AV| 91久久婷婷国产综合精品青草| 热RE99久久精品国产66热| 久久久久99精品成人片欧美| 久久强奷乱码老熟女网站| 久久综合狠狠综合久久| 亚洲第一永久AV网站久久精品男人的天堂AV | 伊人精品久久久久7777| 国产精品99久久精品| 久久精品国产乱子伦| 久久久国产精品| 国产精品成人99久久久久91gav| 97精品伊人久久久大香线蕉| 久久国产精品国语对白| 99久久精品国产高清一区二区 | 97精品伊人久久大香线蕉app| 无码8090精品久久一区| 国产成人精品久久一区二区三区av | 久久99精品国产一区二区三区| 亚洲精品午夜国产va久久| 香港aa三级久久三级| 久久91综合国产91久久精品| 色欲综合久久躁天天躁蜜桃| 综合久久给合久久狠狠狠97色| 久久se精品一区二区影院| 99热热久久这里只有精品68| 精品久久久久久国产| 美女写真久久影院| 91精品国产综合久久四虎久久无码一级|