#define globalfifo_size 0x1000 /*全域性fifo最大4k位元組*/
#define fifo_clear 0x1 /*清0全域性記憶體的長度*/
#define globalfifo_major 200 /*預設的globalfifo的主裝置號*/
static int globalfifo_major = globalfifo_major;
module_param(globalfifo_major, int, s_irugo|s_iwugo);
module_parm_desc(globalfifo_major,"globalfifo major number");
/*globalfifo裝置結構體*/
struct globalfifo_dev
;struct globalfifo_dev *globalfifo_devp; /*裝置結構體指標*/
/*檔案開啟函式*/
int globalfifo_open(struct inode *inode, struct file *filp)
/*檔案釋放函式*/
int globalfifo_release(struct inode *inode, struct file *filp)
/* ioctl裝置控制函式 */
static int globalfifo_ioctl(struct inode *inodep, struct file *filp, unsigned
int cmd, unsigned long arg)
return 0;
}static unsigned int globalfifo_poll(struct file *filp, poll_table *wait)
/*fifo非滿*/
if (dev->current_len != globalfifo_size)
up(&dev->sem);
return mask;
}/*globalfifo讀函式*/
static ssize_t globalfifo_read(struct file *filp, char __user *buf, size_t count,
loff_t *ppos)
__set_current_state(task_interruptible); //改變程序狀態為睡眠
up(&dev->sem);
schedule(); //排程其他程序執行
if (signal_pending(current))
//如果是因為訊號喚醒
down(&dev->sem);
}/* 拷貝到使用者空間 */
if (count > dev->current_len)
count = dev->current_len;
if (copy_to_user(buf, dev->mem, count))
else
out: up(&dev->sem); //釋放訊號量
out2:remove_wait_queue(&dev->w_wait, &wait); //從附屬的等待佇列頭移除
set_current_state(task_running);
return ret;
}/*globalfifo寫操作*/
static ssize_t globalfifo_write(struct file *filp, const char __user *buf,
size_t count, loff_t *ppos)
__set_current_state(task_interruptible); //改變程序狀態為睡眠
up(&dev->sem);
schedule(); //排程其他程序執行
if (signal_pending(current))
//如果是因為訊號喚醒
down(&dev->sem); //獲得訊號量
}/*從使用者空間拷貝到核心空間*/
if (count > globalfifo_size - dev->current_len)
count = globalfifo_size - dev->current_len;
if (copy_from_user(dev->mem + dev->current_len, buf, count))
else
//tasklet_schedule(&dev->tlet);
schedule_work(&dev->my_wq);//排程工作佇列執行
printk("in write jiffies=%d\n",jiffies);
out: up(&dev->sem); //釋放訊號量
out2:remove_wait_queue(&dev->w_wait, &wait); //從附屬的等待佇列頭移除
set_current_state(task_running);
return ret;
}/*檔案操作結構體*/
static const struct file_operations globalfifo_fops =
;/*初始化並註冊cdev*/
static void globalfifo_setup_cdev(struct globalfifo_dev *dev, int index)
/*void jit_tasklet_fn(unsigned long arg)
*/void my_do_work(unsigned long arg)//定義乙個處理函式
/*裝置驅動模組載入函式*/
int globalfifo_init(void)
if (ret < 0)
return ret;
/* 動態申請裝置結構體的記憶體*/
globalfifo_devp = kmalloc(sizeof(struct globalfifo_dev), gfp_kernel);
if (!globalfifo_devp) /*申請失敗*/
memset(globalfifo_devp, 0, sizeof(struct globalfifo_dev));
globalfifo_setup_cdev(globalfifo_devp, 0);
init_mutex(&globalfifo_devp->sem); /*初始化訊號量*/
init_waitqueue_head(&globalfifo_devp->r_wait); /*初始化讀等待佇列頭*/
init_waitqueue_head(&globalfifo_devp->w_wait); /*初始化寫等待佇列頭*/
/* register the tasklet */
// tasklet_init(&globalfifo_devp->tlet, jit_tasklet_fn, (unsigned long)globalfifo_devp);
//初始化工作佇列並將其與處理函式繫結
//init_work(&(globalfifo_devp->my_wq),my_do_work);//for 2.6.20
init_work(&(globalfifo_devp->my_wq),my_do_work,(unsigned long)globalfifo_devp);//for 2.6.14
return 0;
fail_malloc: unregister_chrdev_region(devno, 1);
return ret;
}/*模組解除安裝函式*/
void globalfifo_exit(void)
module_author("song baohua");
module_license("dual bsd/gpl");
module_init(globalfifo_init);
module_exit(globalfifo_exit);
globalfifo驅動例項(poll機制)
阻塞操作是指在執行裝置操作時若不能獲得資源則掛起程序,直到滿足可操作的條件後在進行操作。非阻塞操作的程序在不能進行裝置操作時並不掛起,它或者被放棄,或者不停的查詢,直到可以進行操作為止 喚醒程序的地方最大可能發生在中斷裡面,因為硬體資源獲得的同時往往伴隨著乙個中斷 在使用者程式中,select 和p...
支援非同步通知的globalfifo驅動
驅動程式執行在核心空間中,應用程式執行在使用者空間中,兩者是不能直接通訊的。但在實際應用中,在裝置已經準備好的時候,我們希望通知使用者程式裝置已經ok,使用者程式可以讀取了,這樣應用程式就不需要一直查詢該裝置的狀態,從而節約了資源,這就是非同步通知。好,那下乙個問題就來了,這個過程如何實現呢?簡單,...
驅動篇 支援輪詢操作的 globalfifo 驅動
1.globalfifo 驅動中增加輪詢操作 在 globalfifo 的 poll 函式中,首先將裝置結構體中的 r wait 和 w wait 等待佇列頭新增到等待列表,然後通過判斷 dev current len 是否等於 0 來獲得裝置的可讀狀態,通過判斷 dev current len 是...