娇小w搡bbbb搡bbb,《第一次の人妻》,中国成熟妇女毛茸茸,边啃奶头边躁狠狠躁视频免费观看

Linux驅動之同步、互斥、阻塞的應用

發(fā)布者:美好回憶最新更新時間:2024-08-20 來源: cnblogs關鍵字:Linux驅動  同步  互斥  阻塞 手機看文章 掃描二維碼
隨時隨地手機看文章

同步、互斥、阻塞的概念:


同步:在并發(fā)程序設計中,各進程對公共變量的訪問必須加以制約,這種制約稱為同步。


互斥機制:訪問共享資源的代碼區(qū)叫做臨界區(qū),這里的共享資源可能被多個線程需要,但這些共享資源又不能被同時訪問,因此臨界區(qū)需要以某種互斥機制加以保護,以確保共享資源被互斥訪問。


阻塞與非阻塞:阻塞調用是指調用結果返回之前,當前線程會被掛起,調用線程只有在得到結果之后才會返回。非阻塞調用指在不能立刻得到結果之前,該調用不會阻塞當前線程,而是直接返回。



在按鍵驅動的例子中,如果有多個應用程序調用按鍵驅動的設備文件,這時候就要利用同步與互斥的概念對這個種情況進行處理:


1、利用原子變量標志來判斷設備文件是否被打開,原子變量在操作的時候不能被打斷,它是利用關閉中斷的方式實現(xiàn)的,一旦關閉了中斷,內核將不能對進程進行調度,這就保證了原子性。


直接修改驅動代碼,先定義一個原子變量


 static atomic_t open_flag = ATOMIC_INIT(1);     //定義原子變量open_flag 并初始化為1

接著修改打開文件的函數(shù)與關閉文件的函數(shù),初始化時open_flag 為1,一旦打開函數(shù)被調用則會減1變?yōu)?。關閉函數(shù)被調用后會加1又變成1。


a、在sixth_drv_open 中利用atomic_dec_and_test函數(shù)判斷是否已經被調用,如果返回值為0,說明已經被調用。調用atomic_inc函數(shù),并且返回。


b、在sixth_drv_close中第調用atomic_inc。


static int sixth_drv_open (struct inode * inode, struct file * file)

{

    int ret;



    if(atomic_dec_and_test(&open_flag)==0)//自檢后是否為0,不為0說明已經被人調用

    {

        atomic_inc(&open_flag);//原子變量+1

        return -EBUSY;

    }

    

    ret = request_irq(IRQ_EINT0, buttons_irq, IRQT_BOTHEDGE, 's1', (void * )&pins_desc[0]);

    if(ret)

    {

        printk('open failed 1n');

        return -1;

    }

    ret = request_irq(IRQ_EINT2, buttons_irq, IRQT_BOTHEDGE, 's2', (void * )& pins_desc[1]);

    if(ret)

    {

        printk('open failed 2n');

        return -1;

    }

    ret = request_irq(IRQ_EINT11, buttons_irq, IRQT_BOTHEDGE, 's3', (void * )&pins_desc[2]);

    if(ret)

    {

        printk('open failed 3n');

        return -1;

    }

    ret = request_irq(IRQ_EINT19, buttons_irq, IRQT_BOTHEDGE, 's4', (void * )&pins_desc[3]);

    if(ret)

    {

        printk('open failed 4n');

        return -1;

    }

    

    return 0;

}



static int sixth_drv_close(struct inode * inode, struct file * file)

{

    atomic_inc(&open_flag);//原子變量+1

    

    free_irq(IRQ_EINT0 ,(void * )&pins_desc[0]);


     free_irq(IRQ_EINT2 ,(void * )& pins_desc[1]);


    free_irq(IRQ_EINT11 ,(void * )&pins_desc[2]);


    free_irq(IRQ_EINT19 ,(void * )&pins_desc[3]);


    return 0;

}


2、利用信號量對打開的文件進行保護:信號量(semaphore)是用于保護臨界區(qū)的一種常用方法,只有得到信號量的進程才能執(zhí)行臨界區(qū)代碼。當獲取不到信號量時,進程進入休眠等待狀態(tài)。

 

直接修改驅動代碼,先定義一個互斥鎖

static DECLARE_MUTEX(button_lock);     //定義互斥鎖

接著更改按鍵驅動中打開文件的函數(shù)與關閉文件的函數(shù):


a、在sixth_drv_open函數(shù)中如果文件打開方式非阻塞的,那么調用down_trylock函數(shù)獲取信號量,此函數(shù)如果獲取不到信號量,直接返回;如果打開文件的方式是阻塞的,那么調用down函數(shù),如果獲取不到信號量,則將進程休眠直到獲取信號量為止。


b、在sixth_drv_close函數(shù)利用up函數(shù)直接釋放掉信號量。


static int sixth_drv_open (struct inode * inode, struct file * file)

{

    int ret;


    if(file->f_flags & O_NONBLOCK)//非阻塞方式

    {

        if(down_trylock(&button_lock))//獲取信號量失敗則返回

            return -EBUSY;

    }

    else    

        down(&button_lock);//獲得信號量

    

    ret = request_irq(IRQ_EINT0, buttons_irq, IRQT_BOTHEDGE, 's1', (void * )&pins_desc[0]);

    if(ret)

    {

        printk('open failed 1n');

        return -1;

    }

    ret = request_irq(IRQ_EINT2, buttons_irq, IRQT_BOTHEDGE, 's2', (void * )& pins_desc[1]);

    if(ret)

    {

        printk('open failed 2n');

        return -1;

    }

    ret = request_irq(IRQ_EINT11, buttons_irq, IRQT_BOTHEDGE, 's3', (void * )&pins_desc[2]);

    if(ret)

    {

        printk('open failed 3n');

        return -1;

    }

    ret = request_irq(IRQ_EINT19, buttons_irq, IRQT_BOTHEDGE, 's4', (void * )&pins_desc[3]);

    if(ret)

    {

        printk('open failed 4n');

        return -1;

    }

    

    return 0;

}



static int sixth_drv_close(struct inode * inode, struct file * file)

{

    up(&button_lock);//釋放信號量

    

    free_irq(IRQ_EINT0 ,(void * )&pins_desc[0]);


     free_irq(IRQ_EINT2 ,(void * )& pins_desc[1]);


    free_irq(IRQ_EINT11 ,(void * )&pins_desc[2]);


    free_irq(IRQ_EINT19 ,(void * )&pins_desc[3]);


    return 0;

}


將完整的按鍵驅動的源代碼貼出


#include <linux/module.h>

#include

#include

#include

#include         //含有iomap函數(shù)iounmap函數(shù)

#include //含有copy_from_user函數(shù)

#include //含有類相關的處理函數(shù)

#include gpio.h>//含有S3C2410_GPF0等相關的

#include     //含有IRQ_HANDLEDIRQ_TYPE_EDGE_RISING

#include    //含有IRQT_BOTHEDGE觸發(fā)類型

#include //含有request_irq、free_irq函數(shù)

#include

#include   //含有各種錯誤返回值

//#include




static struct class *sixth_drv_class;//類

static struct class_device *sixth_drv_class_dev;//類下面的設備

static int sixthmajor;


static unsigned long *gpfcon = NULL;

static unsigned long *gpfdat = NULL;

static unsigned long *gpgcon = NULL;

static unsigned long *gpgdat = NULL;


struct fasync_struct *sixth_fasync;

    

static unsigned int key_val;


struct pin_desc 

{

    unsigned int pin;

    unsigned int key_val;

};


static struct pin_desc  pins_desc[4] = 

{

    {S3C2410_GPF0,0x01},

    {S3C2410_GPF2,0x02},

    {S3C2410_GPG3,0x03},

    {S3C2410_GPG11,0x04}

};



static unsigned int ev_press;

static DECLARE_WAIT_QUEUE_HEAD(button_waitq);//注冊一個等待隊列button_waitq


 static atomic_t open_flag = ATOMIC_INIT(1);     //定義原子變量open_flag 并初始化為1


static DECLARE_MUTEX(button_lock);     //定義互斥鎖


 

/*

  *0x01、0x02、0x03、0x04表示按鍵被按下

  */

  

/*

  *0x81、0x82、0x83、0x84表示按鍵被松開

  */


/*

  *利用dev_id的值為pins_desc來判斷是哪一個按鍵被按下或松開

  */

static irqreturn_t buttons_irq(int irq, void *dev_id)

{

    unsigned int pin_val;

    struct pin_desc * pin_desc = (struct pin_desc *)dev_id;//取得哪個按鍵被按下的狀態(tài)

    

    pin_val = s3c2410_gpio_getpin(pin_desc->pin);

    

    if(pin_val) //按鍵松開

        key_val = 0x80 | pin_desc->key_val;

    else

        key_val = pin_desc->key_val;



    wake_up_interruptible(&button_waitq);   /* 喚醒休眠的進程 */

    ev_press = 1;    

    

    kill_fasync(&sixth_fasync, SIGIO, POLL_IN);//發(fā)生信號給進程

    

    return IRQ_HANDLED;

}




static int sixth_drv_open (struct inode * inode, struct file * file)

{

    int ret;



//    if(atomic_dec_and_test(&open_flag)==0)//自檢后是否為0,不為0說明已經被人調用

//    {

//        atomic_inc(&open_flag);//原子變量+1

//        return -EBUSY;

//    }

    if(file->f_flags & O_NONBLOCK)//非阻塞方式

    {

        if(down_trylock(&button_lock))//獲取信號量失敗則返回

            return -EBUSY;

    }

    else    

        down(&button_lock);//獲得信號量

    

    ret = request_irq(IRQ_EINT0, buttons_irq, IRQT_BOTHEDGE, 's1', (void * )&pins_desc[0]);

    if(ret)

    {

        printk('open failed 1n');

        return -1;

    }

    ret = request_irq(IRQ_EINT2, buttons_irq, IRQT_BOTHEDGE, 's2', (void * )& pins_desc[1]);

    if(ret)

    {

        printk('open failed 2n');

        return -1;

    }

    ret = request_irq(IRQ_EINT11, buttons_irq, IRQT_BOTHEDGE, 's3', (void * )&pins_desc[2]);

    if(ret)

    {

        printk('open failed 3n');

        return -1;

    }

    ret = request_irq(IRQ_EINT19, buttons_irq, IRQT_BOTHEDGE, 's4', (void * )&pins_desc[3]);

    if(ret)

    {

        printk('open failed 4n');

        return -1;

    }

    

    return 0;

}



static int sixth_drv_close(struct inode * inode, struct file * file)

{

//    atomic_inc(&open_flag);//原子變量+1

    up(&button_lock);//釋放信號量

    

    free_irq(IRQ_EINT0 ,(void * )&pins_desc[0]);


     free_irq(IRQ_EINT2 ,(void * )& pins_desc[1]);


    free_irq(IRQ_EINT11 ,(void * )&pins_desc[2]);


    free_irq(IRQ_EINT19 ,(void * )&pins_desc[3]);


    return 0;

}


static ssize_t sixth_drv_read(struct file * file, char __user * userbuf, size_t count, loff_t * off)

{

    int ret;


    if(count != 1)

    {

        printk('read errorn');

        return -1;

    }


    if(file->f_flags & O_NONBLOCK)//非阻塞方式

    {

        if(!ev_press)//判斷是否有按鍵按下,如果沒有直接返回

        {

                key_val = 0;

                copy_to_user(userbuf, &key_val, 1);

                return -EBUSY;

        }

    }

    else//如果沒有按鍵動作,直接進入休眠

        wait_event_interruptible(button_waitq, ev_press);//將當前進程放入等待隊列button_waitq中

[1] [2]
關鍵字:Linux驅動  同步  互斥  阻塞 引用地址:Linux驅動之同步、互斥、阻塞的應用

上一篇:Linux驅動之定時器在按鍵去抖中的應用
下一篇:Linux驅動之異步OR同步,阻塞OR非阻塞概念介紹

推薦閱讀最新更新時間:2025-06-07 23:41

手把手教你寫Linux設備驅動---中斷(三)--workqueue實現(xiàn)(基于友善之臂4412開發(fā)板)
上節(jié),我們講到如何來實現(xiàn)tasklet小任務機制 http://blog.csdn.NET/morixinguan/article/details/69666935 這節(jié),我們來實現(xiàn)一下中斷下半部的工作隊列: 在寫這個demo之前,我們要了解一下工作隊列的相關數(shù)據(jù)結構還有API。 需要包含的頭文件: #include Linux/workqueue.h 基本的數(shù)據(jù)結構: //工作隊列結構 struct work_struct { atomic_long_t data; //鏈表處理 struct list_head entry; //工作處理函數(shù) work_func_t
[單片機]
手把手教你寫<font color='red'>Linux</font>設備<font color='red'>驅動</font>---中斷(三)--workqueue實現(xiàn)(基于友善之臂4412開發(fā)板)
tiny4412學習(三)之移植linux-4.x驅動(1)支持網(wǎng)卡驅動
一、思路 上一節(jié)我們通過DNW將內核、文件系統(tǒng)、設備樹文件燒入到內存中,并使用bootm啟動內核:bootm0x40600000 0x41000000 0x42000000。因為此時內核并沒有SD卡驅動,和EMMC驅動,我們只能直接將系統(tǒng)拷貝至內存中然后啟動。當時我們進入文件系統(tǒng)后,并無法掛載外面的網(wǎng)絡文件系統(tǒng),對開發(fā)帶來很多不便,所以這一節(jié),我們移植網(wǎng)卡,讓系統(tǒng)啟動后可以掛接虛擬機中的網(wǎng)絡文件系統(tǒng),或者直接掛載虛擬機中的網(wǎng)絡文件系統(tǒng)。 實驗參考摩斯電碼的博客:http://www.cnblogs.com/pengdonglin137/p/5153794.html tiny4412網(wǎng)卡跟DM9000差別很大,DM9000是
[單片機]
tiny4412學習(三)之移植<font color='red'>linux</font>-4.x<font color='red'>驅動</font>(1)支持網(wǎng)卡<font color='red'>驅動</font>
ARM-Linux驅動移植--DM9000網(wǎng)卡驅動移植
硬件平臺:FL2440 內核版本:2.6.39 主機平臺:Ubuntu 11.04 內核版本:2.6.35 交叉編譯器:arm-linux-gcc 4.3.2 原創(chuàng)作品,轉載請標明出處 http://blog.csdn.net/yming0221/article/details/6641579 1、DM9000網(wǎng)卡驅動的分析請見 http://blog.csdn.net/yming0221/article/details/6609742 2、如果想自己調試DM9000網(wǎng)卡驅動,那么在編譯內核之前將網(wǎng)卡驅動不要編譯進內核,啟動后自己編譯并加載內核 由于一般的驅動或者程序是通過NFS掛載到開發(fā)板上的,所以,如果沒有網(wǎng)卡
[單片機]
ARM-Linux驅動移植--Linux下燒寫工具DNW和USB驅動安裝
主機平臺:Gentoo Linux 11.2 with linux kernel 3.0.6 硬件平臺:FL2440(S3C2440)with linux kernel 2.6.35 原創(chuàng)作品,轉載請標明出處 http://blog.csdn.net/yming0221/article/details/7211396 1、首先下載DNW for linux http://download.csdn.net/source/1011140 2、解壓文件 、 3、編譯主機的USB驅動 make -C /lib/modules/`uname -r`/build M=`pwd` modules 然后insmod
[單片機]
ARM-<font color='red'>Linux</font><font color='red'>驅動</font>移植--<font color='red'>Linux</font>下燒寫工具DNW和USB<font color='red'>驅動</font>安裝
南芯科技推出面向儲能市場的80V高效同步雙向升降壓充電芯片
(2024年11月8日,上海)今日 ,南芯科技 宣布推出全新高效同步雙向升降壓充電芯片 SC8808,可支持最高 80V 的充電電壓,主要面向需求持續(xù)增長的儲能市場,適用于鋰離子電池、磷酸鐵鋰電池組等多種類儲能電池。 除了儲能應用外,SC8808 還可用于電動工具、電動自行車、拓展塢等高功率場景,進一步拓寬了南芯充電芯片的使用場景。 靈活配置,安全升級,激活高效充放電體驗 SC8808 擁有 4.5V-80V 的寬輸入電壓范圍。產品支持雙向工作模式,放電模式下可滿足 PD3.1 EPR 全范圍輸出標準,內部寄存器調壓可輸出 5V-48V 的電壓,且調壓步進滿足 PPS 和 EPR AVS 要求。 SC8808 可以
[電源管理]
南芯科技推出面向儲能市場的80V高效<font color='red'>同步</font>雙向升降壓充電芯片
一種用于同步磁阻牽引電機的新型取向鋼疊片轉子鐵心
技術進步極大推動了全球電氣化進程,因此動力系統(tǒng)選擇合適的電機至關重要。尤其在電動汽車行業(yè)中,選擇具有更高性能和更低成本的電機需求正在快速增長。 同步磁阻電機(SynRM)中轉子的各向異性有助于減少昂貴的稀土永磁體以及銅條或鋁條的使用。因此與永磁體(PMSM)和感應電機(IM)相比,同步電機可能提供更高的性價比,成為未來牽引電機電氣化動力傳動系統(tǒng)強大的潛力市場。 對于高性能SynRM的設計來說,往往希望最大程度的獲得高Ld或低Lq指標,同時由于電動汽車的高速特性,研究新的轉子結構和幾何形狀,可以實現(xiàn)機械穩(wěn)健運行。 冷軋晶粒取向鋼(CRGO)是在嚴格的工藝控制下加工生產的產品,具有在軋制方向上合適的磁性和非常高的堆積因子。因此
[嵌入式]
一種用于<font color='red'>同步</font>磁阻牽引電機的新型取向鋼疊片轉子鐵心
遠翔FP6161:1A同步降壓IC
FP6161是一種高效電流模式同步巴PWM直流-直流調節(jié)器。內部產生的0.6V精度反饋參考電壓設計用于低輸出電壓。低RDS(ON)同步開關可顯著降低傳導損耗。為了延長便攜式應用的電池壽命,低輟學操作支持100%占空比。關機模式還有助于節(jié)省當前的消耗。FP6161被封裝在DFN-6L、SOT23-5L和TSOT23-5L中,以減少PCB空間。 特色 ?輸入電壓范圍:2.5至5.5V ?精密反饋參考電壓:0.6V(±2%) ?輸出電流:1A(最大)。 ?占空比:0~100% ?內部固定PWM頻率:1.5MHz ?低靜止電流:100μA ?沒有肖特基二極管需要 ?內置軟啟動 ?電流模式操作 ?過溫度保護 ?封裝:DFN-6L(2x2
[嵌入式]
遠翔FP6161:1A<font color='red'>同步</font>降壓IC
車載以太網(wǎng)時間同步Time Master行為
Time Master行為 在gPTP網(wǎng)絡中作為Time Master的節(jié)點存在著如下報文處理流程: Time Master負責SYNC報文與Follow-Up報文的發(fā)送,SYNC報文可以通過設置參數(shù)EthTSynGlobalTimeTxPeriod來進行周期性發(fā)送,在發(fā)送SYNC報文的過程中需進行如下三個基本步驟: 通過函數(shù) EthIf_ProvideTxBuffer來獲取空閑的buffer來存儲發(fā)送的數(shù)據(jù); 如果參數(shù)EthTSynHardwareTimestampSupport設置為TRUE,那么可通過函數(shù)EthIf_EnableEgressTimeStamp來激活硬件時間戳功能; 通過調用函數(shù)Ethif_Transmit
[嵌入式]
小廣播
設計資源 培訓 開發(fā)板 精華推薦

最新單片機文章

 
EEWorld訂閱號

 
EEWorld服務號

 
汽車開發(fā)圈

 
機器人開發(fā)圈

電子工程世界版權所有 京ICP證060456號 京ICP備10001474號-1 電信業(yè)務審批[2006]字第258號函 京公網(wǎng)安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 临湘市| 罗平县| 庆云县| 峨边| 麻江县| 黑龙江省| 桐梓县| 阿瓦提县| 华坪县| 康保县| 香河县| 无锡市| 沂南县| 郓城县| 十堰市| 濮阳市| 河南省| 岳西县| 临邑县| 垣曲县| 通化市| 桐柏县| 霞浦县| 盘山县| 壶关县| 湾仔区| 晋宁县| 祁东县| 广灵县| 峨山| 德昌县| 黄石市| 兴国县| 乌拉特中旗| 黄骅市| 皋兰县| 四川省| 天长市| 民勤县| 郴州市| 彰化县|