裝置驅動程式:
#include
#include
#include
#include
#include
#include
#include
module_license("gpl");
#define buf_size 256
#define device ((const char*)"kgrunt")
struct kgrunt_dev
struct cdev cdev;
char *buf;
int len;
int bytes;
struct timer_list timer;
int timer_flag;
wait_queue_head_t queue;
dev_t dev;
static struct kgrunt_dev kgrunt;
static void kgrunt_timer_fn(unsigned long d)
struct kgrunt_dev *dev = (struct kgrunt_dev *)d;
struct timer_list *timer = &dev->timer;
dev->bytes = snprintf(dev->buf, dev->len,\
"timer experis: %lu,jiffers: %lu, current pid: %d, comm:%s\n",\
timer->expires,jiffies, current->pid, current->comm);
wake_up_interruptible(&dev->queue);//喚醒等待佇列
if (dev->timer_flag)
mod_timer(timer, timer->expires + hz);
static int kgrunt_open(struct inode *inode, struct file *file)
printk("kgrunt open\n");
struct kgrunt_dev *dev = \
container_of(inode->i_cdev, struct kgrunt_dev, cdev);//由
inode
對應的字元裝置指標得到
kgrunt
裝置的位址
file->private_data = dev;
mod_timer(&dev->timer, jiffies + hz);//註冊定時器
dev->timer_flag = 1;
return 0;
static int kgrunt_realse(struct inode *inode, struct file *file)
printk("kgrunt release\n");
struct kgrunt_dev * dev = container_of(inode->i_cdev, struct kgrunt_dev, cdev);
dev->timer_flag = 0;
del_timer_sync(&dev->timer);
return 0;
static ssize_t kgrunt_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
int err;
struct kgrunt_dev *dev = (struct kgrunt_dev *)file->private_data;
printk("read data ,count: %d, pos: %d\n", count, (int)*pos);
if (count < 0)
return -einval;
if (count == 0)
return 0;
if (dev->bytes == 0)
if (file->f_flags & o_nonblock)
return -eagain;
err = wait_event_interruptible(dev->queue, dev->bytes > 0);//等待佇列
if (err == erestartsys)
return -eintr;
if (count > dev->bytes)
count = dev->bytes;
if (copy_to_user(buf, dev->buf, count) > 0)
printk("copy data to user failed\n");
return -efault;
dev->bytes = 0;
return count;
static ssize_t kgrunt_write(struct file *file, char __user *buf, size_t count, loff_t *pos)
/*nothing to do*/
return -eperm;
static loff_t kgrunt_llseek(struct file *file, loff_t offset, int whence)
/*nothing to do*/
return -eperm;
static struct file_operations kgrunt_fops =
.owner = this_module,
.open = kgrunt_open,
.release= kgrunt_realse,
.read = kgrunt_read,
.write = kgrunt_write,
.llseek = kgrunt_llseek,
static __init int kgrunt_init(void)
int err;
printk("init kgrunt\n");
if ((err = alloc_chrdev_region(&kgrunt.dev, 0, 1, device)) < 0)//自動註冊裝置號
printk("alloc_chardev_region err\n");
goto cdev_alloc_fail;
printk("major: %d, minor: %d\n", major(kgrunt.dev), minor(kgrunt.dev));
if ((kgrunt.buf = kmalloc(buf_size, gfp_kernel)) == null)
goto kmalloc_fali;
printk("kmalloc succfull\n");
kgrunt.len = buf_size;
kgrunt.bytes = 0;
cdev_init(&kgrunt.cdev, &kgrunt_fops);//初始化裝置
kgrunt.cdev.owner = kgrunt_fops.owner;
setup_timer(&kgrunt.timer, kgrunt_timer_fn, (unsigned long)&kgrunt);//初始化、設定定時器
kgrunt.timer_flag = 0;
init_waitqueue_head(&kgrunt.queue);//初始化等待佇列
if ((err = cdev_add(&kgrunt.cdev, kgrunt.dev, 1)) < 0)//註冊裝置
printk("cedv_add fail\n");
goto cdev_add_fail;
return 0;
cdev_add_fail:
kfree(&kgrunt.buf);
kmalloc_fali:
unregister_chrdev_region(kgrunt.dev, 1);
cdev_alloc_fail:
return err;
static __exit void kgrunt_exit(void)
printk("kgrunt exit\n");
cdev_del(&kgrunt.cdev);
kfree(kgrunt.buf);
unregister_chrdev_region(kgrunt.dev, 1);
module_init(kgrunt_init);
module_exit(kgrunt_exit);
應用程式:
#include
#include
#include
#include
#include
#include
#define device (const char*)"/dev/kgrunt"
int main(int argc, char **argv)
char buf[256];
int fd, ret;
memset(buf, 0, sizeof(buf));
if ((fd = open(device, o_rdonly)) < 0)
printf("open device failed\n");
return 0;
while(1)
memset(buf, 0, sizeof(buf));
if ((ret = read(fd, buf, sizeof(buf))) < 0)
sleep(1);
continue;
sleep(1);
printf("read data: %s\n", buf);
Linux 裝置驅動 核心等待佇列
在 linux 驅動程式設計中,可以使用等待佇列來實現程序的阻塞.等待佇列可以看作儲存程序的容器,在阻塞程序時,將程序放入等待佇列 當喚醒程序時,從等待佇列中取出程序.linux 2.6 核心提供了如下關於等待佇列的操作 wait queue head t my queue init waitque...
《Linux裝置驅動開發詳解》 等待佇列
基礎知識 阻塞與非阻塞 阻塞操作是指在執行裝置操作時若不能獲得資源則掛起程序,直到滿足可操作的條件後再進行操作。被掛起的程序進入休眠狀態,被從排程器的執行佇列移走,直到等待的條件被滿足。而非阻塞操作的程序在不能進行裝置操作時並不掛起,它或者放棄,或者不停地查詢,直至可以進行操作為止。驅動程式通常需要...
Linux 裝置驅動阻塞 非阻塞IO 等待佇列
阻塞 顧名思義,就是指在執行裝置操作時若不能獲得資源則掛起操作,直到滿足可操作的條件後再進行操作,被掛起的程序進入休眠狀態,被從排程器的執行佇列移 走,直到等待的條件滿足。非阻塞 就是反過來,程序在不能進行裝置操作時並不掛起,它或者放棄,或者不停的查詢,直到可以進行位置。小王,明白了沒這兩個基本的概...