Linux驅(qū)動(dòng)總結(jié)3
3、確定一個(gè)具體的條件,比如數(shù)據(jù)有無,具體的條件根據(jù)實(shí)際的情況設(shè)計(jì)。
/*等待條件*/
static bool havedata = false;
4、在需要堵塞的讀函數(shù),寫函數(shù)中分別實(shí)現(xiàn)堵塞,首先定義等待隊(duì)列的節(jié)點(diǎn),并添加到隊(duì)列中去,然后等待事件的喚醒進(jìn)程。但是由于讀寫操作的兩個(gè)等待隊(duì)列都是基于條件havedata的,所以在讀完成以后需要喚醒寫,寫完成以后需要喚醒讀操作,同時(shí)更新條件havedata,最后還要移除添加的等待隊(duì)列節(jié)點(diǎn)。
/*read函數(shù)的實(shí)現(xiàn)*/
static ssize_t mem_read(struct file *filp,char __user *buf, size_t size,loff_t *ppos)
{
unsigned long p = *ppos;
unsigned int count = size;
int ret = 0;
struct mem_dev *dev = filp->private_data;
/*參數(shù)的檢查,首先判斷文件位置*/
if(p >= MEMDEV_SIZE)
return 0;
/*改正文件大小*/
if(count > MEMDEV_SIZE - p)
count = MEMDEV_SIZE - p;
#if 0
/*添加一個(gè)等待隊(duì)列節(jié)點(diǎn)到當(dāng)前進(jìn)程中*/
DECLARE_WAITQUEUE(wait_r,current);
/*將節(jié)點(diǎn)添加到等待隊(duì)列中*/
add_wait_queue(&dev->rdqueue,&wait_r);
/*添加等待隊(duì)列,本來采用if即可,但是由于信號(hào)等可能導(dǎo)致等待隊(duì)列的喚醒,因此采用循環(huán),確保不會(huì)出現(xiàn)誤判*/
#endif
while(!havedata)
{
/*判斷用戶是否設(shè)置為非堵塞模式讀,告訴用戶再讀*/
if(filp->f_flags & O_NONBLOCK)
return -EAGAIN;
/*依據(jù)條件havedata判斷隊(duì)列的狀態(tài),防止進(jìn)程被信號(hào)喚醒*/
wait_event_interruptible(dev->rdqueue,havedata);
}
spin_lock(&dev->lock);
/*從內(nèi)核讀數(shù)據(jù)到用戶空間,實(shí)質(zhì)就通過private_data訪問設(shè)備*/
if(copy_to_user(buf,(void *)(dev->data p),count))
{
/*出錯(cuò)誤*/
ret = -EFAULT;
}
else
{
/*移動(dòng)當(dāng)前文件光標(biāo)的位置*/
*ppos = count;
ret = count;
printk(KERN_INFO "read %d bytes(s) from %d",count,p);
}
spin_unlock(&dev->lock);
#if 0
/*將等待隊(duì)列節(jié)點(diǎn)從讀等待隊(duì)列中移除*/
remove_wait_queue(&dev->rdqueue,&wait_r);
#endif
/*更新條件havedate*/
havedata = false;
/*喚醒寫等待隊(duì)列*/
wake_up_interruptible(&dev->wrqueue);
return ret;
}
/*write函數(shù)的實(shí)現(xiàn)*/
static ssize_t mem_write(struct file *filp,const char __user *buf,size_t size,loff_t *ppos)
{
unsigned long p = *ppos;
unsigned int count = size;
int ret = 0;
/*獲得設(shè)備結(jié)構(gòu)體的指針*/
struct mem_dev *dev = filp->private_data;
/*檢查參數(shù)的長(zhǎng)度*/
if(p >= MEMDEV_SIZE)
return 0;
if(count > MEMDEV_SIZE - p)
count = MEMDEV_SIZE - p;
#if 0
/*定義并初始化一個(gè)等待隊(duì)列節(jié)點(diǎn),添加到當(dāng)前進(jìn)程中*/
DECLARE_WAITQUEUE(wait_w,current);
/*將等待隊(duì)列節(jié)點(diǎn)添加到等待隊(duì)列中*/
add_wait_queue(&dev->wrqueue,&wait_w);
#endif
/*添加寫堵塞判斷*/
/*為何采用循環(huán)是為了防止信號(hào)等其他原因?qū)е聠拘?/
while(havedata)
{
/*如果是以非堵塞方式*/
if(filp->f_flags & O_NONBLOCK)
return -EAGAIN;
/*分析源碼發(fā)現(xiàn),wait_event_interruptible 中存在DECLARE_WAITQUEUE和add_wait_queue的操作,因此不需要手動(dòng)添加等待隊(duì)列節(jié)點(diǎn)*/
wait_event_interruptible(&dev->wrqueue,(!havedata));
}
spin_lock(&dev->lock);
if(copy_from_user(dev->data p,buf,count))
ret = -EFAULT;
else
{
/*改變文件位置*/
*ppos = count;
ret = count;
printk(KERN_INFO "writted %d bytes(s) from %d",count,p);
}
spin_unlock(&dev->lock);
#if 0
/*將該等待節(jié)點(diǎn)移除*/
remove_wait_queue(&dev->wrqueue,&wait_w);
#endif
/*更新條件*/
havedata = true;
/*喚醒讀等待隊(duì)列*/
wake_up_interruptible(&dev->rdqueue);
return ret;
}
關(guān)鍵詞:
Linux驅(qū)動(dòng)總
相關(guān)推薦
技術(shù)專區(qū)
- FPGA
- DSP
- MCU
- 示波器
- 步進(jìn)電機(jī)
- Zigbee
- LabVIEW
- Arduino
- RFID
- NFC
- STM32
- Protel
- GPS
- MSP430
- Multisim
- 濾波器
- CAN總線
- 開關(guān)電源
- 單片機(jī)
- PCB
- USB
- ARM
- CPLD
- 連接器
- MEMS
- CMOS
- MIPS
- EMC
- EDA
- ROM
- 陀螺儀
- VHDL
- 比較器
- Verilog
- 穩(wěn)壓電源
- RAM
- AVR
- 傳感器
- 可控硅
- IGBT
- 嵌入式開發(fā)
- 逆變器
- Quartus
- RS-232
- Cyclone
- 電位器
- 電機(jī)控制
- 藍(lán)牙
- PLC
- PWM
- 汽車電子
- 轉(zhuǎn)換器
- 電源管理
- 信號(hào)放大器
評(píng)論