<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > Linux內(nèi)核開發(fā)之并發(fā)控制(一)

          Linux內(nèi)核開發(fā)之并發(fā)控制(一)

          作者: 時間:2016-12-19 來源:網(wǎng)絡 收藏

            “小濤,你說十一黃金周,火車站,飛機場那些售票系統(tǒng)咋沒一個宕掉的呢。你不宕掉也沒關系,來兩個賣錯票的,說不定哥就去上??词啦?,去北京看青梅竹馬的表妹了…”小王抱怨道。

          本文引用地址:http://www.ex-cimer.com/article/201612/341755.htm

            “暈死..哥鄙視你,你說都老大不小的人了,怎么腦子里天天都是MM之類的事了,能不能有點男子氣概啊..”。

            “靠,能跟你比啊,你是飽漢不知餓漢饑,要是像你一樣十一和…”

            "嗯,啊,哼哼.."沒等他說完,我趕忙塞了雙臭襪子(哪天的也記不住了)?!暗玫茫琁 服了 you,ok”。

            “不過話說回來,小王,你說的還真是個問題,想想這樣的問題,你和GF兩個要去西湖看白娘子,偏偏遇到老天跟你過不去,就只剩下一張票了,你和GF兩個誰去…“

            "不是吧,我這命苦,好不容易有個GF,應該不會出現(xiàn)的,呵呵,如果出現(xiàn)…那好辦,我和她商量好,咱們一起在晚上12:00一起買票,這樣我們兩邊的售票員怎么看都各自有一張票,我們兩個就可以一起了"小王狡黠的笑著。

            “笨,我一口一個鹽水噴死你,分明一張票,你們兩個同一個時間去兩個不同的售票點去買,它還是一張票,怎么可能說去兩個不同地方,兩個售票員都看到有一張票,然后就把這唯一的一張同時賣給了你們兩個人”我打斷到。"算了,看在室友兼我的最忠實狗仔隊員的身份,哥就傳授一招只傳MM的絕學----設備驅(qū)動程序之并發(fā)控制"。

            聽說過并發(fā)沒,那你肯定聽說過競爭,比如競爭上崗,還有你最熟悉的追MM,這也是競爭。那么

            并發(fā)(concurrency)就是說多個執(zhí)行單元同時,并行被執(zhí)行,這多個單元卻不巧要同時訪問一些資源。這其中要分三種情況:

              

           

            正所謂:道高一尺,魔高一丈,你孫悟空有72變,人家二郎神還有73變不是。有問題,沒關系,找小濤哥不是..呵呵?,F(xiàn)在就教你幾招以備不時只需:

            大家不是要競爭嗎,那好,總體原則就是不讓你競爭:保證一個執(zhí)行單元在訪問共享資源的時候,其他的執(zhí)行單元被禁止訪問,將競爭扼殺在萌芽狀態(tài)。這就是傳說中的對共享資源的互斥訪問。

            出招表一:中斷屏蔽(可以保證正在執(zhí)行的執(zhí)行路徑不被中斷處理程序搶占,由于的進程調(diào)度都依賴中斷來實現(xiàn),搶占進程之間的競態(tài)就不存在了)

            使用方法: local_irq_disable() //屏蔽中斷 說明:local_irq_disable()和local_irq_enable()都只能禁止和使能本CPU內(nèi)的中斷

            …. 并不能解決SMP多CPU引發(fā)的競爭。

            critical section //臨界區(qū)

            ….

            local_irq_enable() //開中斷

            與local_irq_disable()不同,local_irq_save(flags)除了進行禁止中斷操作以外,還保證目前CPU的中斷位信息,local_irq_save(flags)進行相反的操作。

            致命弱點: 由于系統(tǒng)的異步I/O,進程調(diào)度等很多重要操作都依賴于中斷,在屏蔽中斷期間所有的中斷都無法處理,因此長時間屏蔽中斷是很危險的,有可能造

            成數(shù)據(jù)丟失甚至系統(tǒng)奔潰。

            出招表二:原子操作(忘了是物理還是化學老師拉著我的手說:原子是最小的,不能再分的東西.看多形象,執(zhí)行過程不能被別的代碼路徑中斷的操作就是原子操作,還

            想跟我競爭,門都沒有)。 分為整形原子和位原子操作。

            使用方法一:整形原子操作

            1)設置原子變量的值

            void atomic_set(atomic_t *v, int i);//設置原子變量的值為i

            atomic_t v = ATOMIC_INIT(0);//定義原子變量v并初始化為0

            2)獲取原子變量的值

            atomic_read(atomic_t *v);//返回原子變量的值

            3)原子變量加/減

            void atomic_add(int i,atomic_t *v); //原子變量增加i

            void atomic_sub(int i,atomic_t *v); //原子變量減少i

            4)原子變量自增/自減

            void atomic_inc(atomic_t *v); //原子變量加1

            void atomic_dec(atomic_t *v); //原子變量減1

            5)操作并測試

            int atomic_inc_and_test(atomic_t *v);//這些操作對原子變量執(zhí)行自增,自減,減操作后測試是否為0,是返回true,否則返回false

            int atomic_dec_and_test(atomic_t *v);

            int atomic_sub_and_test(int i, atomic_t *v);

            6)操作并返回

            int atomic_add_return(int i,atomic_t *v); //這些操作對原子變量進行對應操作,并返回新的值。

            int atomic_sub_return(int i, atomic_t *v);

            int atomic_inc_return(atomic *v);

            int atomic_dec_return(atomic_t *v);

            使用方法二:位原子操作。

            1)設置位

            void set_bit(nr, void *addr); //設置addr地址的第nr位,所謂設置位即將位寫為1

            2)清除位

            void clear_bit(nr,void *addr); //清除addr地址的第nr位,所謂清除位即將位寫為0

            3)改變位

            void change_bit(nr,void *addr); //對addr地址的第nr位反置

            4)測試位

            void test_bit(nr, void *addr); //返回addr地址的第nr位

            5)測試并操作位

            int test_and_set_bit(nr, void *addr);

            int test_and_clear_bit(nr, void *addr);

            int test_and_change_bit(nr, void *addr);

            光說不練,不是好漢。這誰說的呢,咋就是記不得呢,看段代碼:

            static atomic_t ato_avi = ATOMIC_INIT(1); //定義原子變量

            static int ato_open(struct inode *inode, struct file *filp)

            {

            ...

            if (!atomic_dec_and_test(&ato_avi))

            {

            atomic_inc(&ato_avi);

            return = - EBUSY; //已經(jīng)打開

            }

            ..

            return 0; //已經(jīng)打開

            }

            static int ato_release(struct inode *inode, struct file *filp)

            {

            atomic_inc(&ato_avi);

            return 0;

            }

            出招表三:自旋鎖。正如其名,CPU上將要執(zhí)行的代碼將會執(zhí)行一個測試并設置某個內(nèi)存變量的原子操作,若測試結(jié)果表明鎖已經(jīng)空閑,則程序獲得這個自旋

            鎖繼續(xù)運行;若仍被占用,則程序?qū)⒃谝粋€小的循環(huán)內(nèi)重復測試這個"測試并設置"的操作.這就是自旋。

            使用方法:1)spinlock_t spin; //定義自旋鎖

            2)spin_lock_init(lock); //初始化自旋鎖

            3)spin_lock(lock); //成功獲得自旋鎖立即返回,否則自旋在那里直到該自旋鎖的保持者釋放

            spin_trylock(lock); //成功獲得自旋鎖立即返回真,否則返回假,而不是像上一個那樣"在原地打轉(zhuǎn)"

            4)spin_unlock(lock);//釋放自旋鎖

            自旋鎖一般像下邊這樣使用:

            spinlock_t lock;

            spin_lock_init(&lock);

            spin_lock (&lock);

            ....//臨界區(qū)

            spin_unlock(&lock);

            還記的前邊說的第一招:中斷屏蔽中致命的弱點步,自旋鎖就是針對SMP或單個CPU但內(nèi)核可搶占的情況,對于但CPU和內(nèi)核不可搶占的系統(tǒng),自旋鎖退化為空操作。還有就是自旋鎖解決了臨界區(qū)不受別的CPU和本CPU內(nèi)的搶占進程打擾,但是得到鎖的代碼路徑在執(zhí)行臨界區(qū)的時候還可能受到中斷和底半部的影響。

            那咋辦呢,天要下雨,娘要嫁人,可二郎神的就是比你孫悟空多了一變,你能咋辦,打一架?打不過..所以說嘛,Linux社區(qū)的開發(fā)者們早想到了辦法:在自旋鎖的基礎上進行衍生,具體是怎么回事,且聽下回分解(每次說這句話是感覺好爽,這難道就是高手??岬臉啡?.)..



          關鍵詞: Linux 內(nèi)核

          評論


          相關推薦

          技術專區(qū)

          關閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();