[置頂] Linux裝置驅動,等待隊列

來源:互聯網
上載者:User

裝置驅動程式:

#include <linux/module.h>

#include <linux/fs.h>

#include <linux/cdev.h>

#include <linux/uaccess.h>

#include <linux/timer.h>

#include <linux/sched.h>

#include <linux/wait.h>

 

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 <stdio.h>

#include <string.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <unistd.h>

 

#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);

}

}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.