字符设备驱动poll函数

  1. #ifndef _MEMDEV_H_
  • #define _MEMDEV_H_

  • #ifndef MEMDEV_MAJOR
  • #define MEMDEV_MAJOR 0 /*预设的mem的主设备号*/
  • #endif

  • #ifndef MEMDEV_NR_DEVS
  • #define MEMDEV_NR_DEVS 2 /*设备数*/
  • #endif

  • #ifndef MEMDEV_SIZE
  • #define MEMDEV_SIZE 4096
  • #endif

  • /*mem设备描述结构体*/
  • struct mem_dev
  • {
  •   char *data;
  •   unsigned long size;
  •   wait_queue_head_t inq;
  • };

  • #endif /* _MEMDEV_H_ */
    1. #include <linux/module.h>
    2. #include <linux/types.h>
    3. #include <linux/fs.h>
    4. #include <linux/errno.h>
    5. #include <linux/mm.h>
    6. #include <linux/sched.h>
    7. #include <linux/init.h>
    8. #include <linux/cdev.h>
    9. #include <asm/io.h>
    10. #include <asm/system.h>
    11. #include <asm/uaccess.h>

    12. #include <linux/poll.h>
    13. #include "memdev.h"

    14. static mem_major = MEMDEV_MAJOR;
    15. bool have_data = false; /*表明设备有足够数据可供读*/

    16. module_param(mem_major, int, S_IRUGO);

    17. struct mem_dev *mem_devp; /*设备结构体指针*/

    18. struct cdev cdev;

    19. /*文件打开函数*/
    20. int mem_open(struct inode *inode, struct file *filp)
    21. {
    22.     struct mem_dev *dev;
    23.    
    24.     /*获取次设备号*/
    25.     int num = MINOR(inode->i_rdev);

    26.     if (num >= MEMDEV_NR_DEVS)
    27.             return -ENODEV;
    28.     dev = &mem_devp[num];
    29.    
    30.     /*将设备描述结构指针赋值给文件私有数据指针*/
    31.     filp->private_data = dev;
    32.    
    33.     return 0;
    34. }

    35. /*文件释放函数*/
    36. int mem_release(struct inode *inode, struct file *filp)
    37. {
    38.   return 0;
    39. }

    40. /*读函数*/
    41. static ssize_t mem_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
    42. {
    43.   unsigned long p = *ppos;
    44.   unsigned int count = size;
    45.   int ret = 0;
    46.   struct mem_dev *dev = filp->private_data; /*获得设备结构体指针*/

    47.   /*判断读位置是否有效*/
    48.   if (p >= MEMDEV_SIZE)
    49.     return 0;
    50.   if (count > MEMDEV_SIZE - p)
    51.     count = MEMDEV_SIZE - p;
    52.    
    53.   while (!have_data) /* 没有数据可读,考虑为什么不用if,而用while */
    54.   {
    55.         if (filp->f_flags & O_NONBLOCK)
    56.             return -EAGAIN;
    57.    
    58.     wait_event_interruptible(dev->inq,have_data);
    59.   }

    60.   /*读数据到用户空间*/
    61.   if (copy_to_user(buf, (void*)(dev->data + p), count))
    62.   {
    63.     ret = - EFAULT;
    64.   }
    65.   else
    66.   {
    67.     *ppos += count;
    68.     ret = count;
    69.   
    70.     printk(KERN_INFO "read %d bytes(s) from %d\n", count, p);
    71.   }
    72.  
    73.   have_data = false; /* 表明不再有数据可读 */
    74.   /* 唤醒写进程 */
    75.   return ret;
    76. }

    77. /*写函数*/
    78. static ssize_t mem_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)
    79. {
    80.   unsigned long p = *ppos;
    81.   unsigned int count = size;
    82.   int ret = 0;
    83.   struct mem_dev *dev = filp->private_data; /*获得设备结构体指针*/
    84.  
    85.   /*分析和获取有效的写长度*/
    86.   if (p >= MEMDEV_SIZE)
    87.     return 0;
    88.   if (count > MEMDEV_SIZE - p)
    89.     count = MEMDEV_SIZE - p;

    90.   /*从用户空间写入数据*/
    91.   if (copy_from_user(dev->data + p, buf, count))
    92.     ret = - EFAULT;
    93.   else
    94.   {
    95.     *ppos += count;
    96.     ret = count;
    97.    
    98.     printk(KERN_INFO "written %d bytes(s) from %d\n", count, p);
    99.   }
    100.  
    101.   have_data = true; /* 有新的数据可读 */
    102.    
    103.     /* 唤醒读进程 */
    104.     wake_up(&(dev->inq));

    105.   return ret;
    106. }

    107. /* seek文件定位函数 */
    108. static loff_t mem_llseek(struct file *filp, loff_t offset, int whence)
    109. {
    110.     loff_t newpos;

    111.     switch(whence) {
    112.       case 0: /* SEEK_SET */
    113.         newpos = offset;
    114.         break;

    115.       case 1: /* SEEK_CUR */
    116.         newpos = filp->f_pos + offset;
    117.         break;

    118.       case 2: /* SEEK_END */
    119.         newpos = MEMDEV_SIZE -1 + offset;
    120.         break;

    121.       default: /* can't happen */
    122.         return -EINVAL;
    123.     }
    124.     if ((newpos<0) || (newpos>MEMDEV_SIZE))
    125.         return -EINVAL;
    126.        
    127.     filp->f_pos = newpos;
    128.     return newpos;

    129. }

    130. unsigned int mem_poll(struct file *filp, poll_table *wait)
    131. {
    132.     struct mem_dev *dev = filp->private_data;
    133.     unsigned int mask = 0;
    134.    
    135.    /*将等待队列添加到poll_table */
    136.     poll_wait(filp, &dev->inq, wait);

    137.    
    138.     if (have_data) mask |= POLLIN | POLLRDNORM; /* readable */

    139.     return mask;
    140. }


    141. /*文件操作结构体*/
    142. static const struct file_operations mem_fops =
    143. {
    144.   .owner = THIS_MODULE,
    145.   .llseek = mem_llseek,
    146.   .read = mem_read,
    147.   .write = mem_write,
    148.   .open = mem_open,
    149.   .release = mem_release,
    150.   .poll = mem_poll,
    151. };

    152. /*设备驱动模块加载函数*/
    153. static int memdev_init(void)
    154. {
    155.   int result;
    156.   int i;

    157.   dev_t devno = MKDEV(mem_major, 0);

    158.   /* 静态申请设备号*/
    159.   if (mem_major)
    160.     result = register_chrdev_region(devno, 2, "memdev");
    161.   else /* 动态分配设备号 */
    162.   {
    163.     result = alloc_chrdev_region(&devno, 0, 2, "memdev");
    164.     mem_major = MAJOR(devno);
    165.   }
    166.  
    167.   if (result < 0)
    168.     return result;

    169.   /*初始化cdev结构*/
    170.   cdev_init(&cdev, &mem_fops);
    171.   cdev.owner = THIS_MODULE;
    172.   cdev.ops = &mem_fops;
    173.  
    174.   /* 注册字符设备 */
    175.   cdev_add(&cdev, MKDEV(mem_major, 0), MEMDEV_NR_DEVS);
    176.   
    177.   /* 为设备描述结构分配内存*/
    178.   mem_devp = kmalloc(MEMDEV_NR_DEVS * sizeof(struct mem_dev), GFP_KERNEL);
    179.   if (!mem_devp) /*申请失败*/
    180.   {
    181.     result = - ENOMEM;
    182.     goto fail_malloc;
    183.   }
    184.   memset(mem_devp, 0, sizeof(struct mem_dev));
    185.  
    186.   /*为设备分配内存*/
    187.   for (i=0; i < MEMDEV_NR_DEVS; i++)
    188.   {
    189.         mem_devp[i].size = MEMDEV_SIZE;
    190.         mem_devp[i].data = kmalloc(MEMDEV_SIZE, GFP_KERNEL);
    191.         memset(mem_devp[i].data, 0, MEMDEV_SIZE);
    192.  
    193.       /*初始化等待队列*/
    194.      init_waitqueue_head(&(mem_devp[i].inq));
    195.      //init_waitqueue_head(&(mem_devp[i].outq));

    196.   }
    197.   
    198.   return 0;

    199.   fail_malloc:
    200.   unregister_chrdev_region(devno, 1);
    201.  
    202.   return result;
    203. }

    204. /*模块卸载函数*/
    205. static void memdev_exit(void)
    206. {
    207.   cdev_del(&cdev); /*注销设备*/
    208.   kfree(mem_devp); /*释放设备结构体内存*/
    209.   unregister_chrdev_region(MKDEV(mem_major, 0), 2); /*释放设备号*/
    210. }

    211. MODULE_AUTHOR("David Xie");
    212. MODULE_LICENSE("GPL");

    213. module_init(memdev_init);
    214. module_exit(memdev_exit);
    1. #include <stdio.h>

    2. int main()
    3. {
    4.     FILE *fp = NULL;
    5.     char Buf[128];
    6.        
    7.     /*打开设备文件*/
    8.     fp = fopen("/dev/memdev0","r+");
    9.     if (fp == NULL)
    10.     {
    11.         printf("Open Dev memdev Error!\n");
    12.         return -1;
    13.     }
    14.    
    15.     /*写入设备*/
    16.     strcpy(Buf,"memdev is char dev!");
    17.     printf("Write BUF: %s\n",Buf);
    18.     fwrite(Buf, sizeof(Buf), 1, fp);
    19.    
    20.     sleep(5);
    21.     fclose(fp);
    22.    
    23.     return 0;   

    24. }
    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. #include <unistd.h>
    4. #include <sys/ioctl.h>
    5. #include <sys/types.h>
    6. #include <sys/stat.h>
    7. #include <fcntl.h>
    8. #include <sys/select.h>
    9. #include <sys/time.h>
    10. #include <errno.h>

    11. int main()
    12. {
    13.     int fd;
    14.     fd_set rds;
    15.     int ret;
    16.     char Buf[128];
    17.    
    18.     /*初始化Buf*/
    19.     strcpy(Buf,"memdev is char dev!");
    20.     printf("BUF: %s\n",Buf);
    21.    
    22.     /*打开设备文件*/
    23.     fd = open("/dev/memdev0",O_RDWR);
    24.    
    25.     FD_ZERO(&rds);
    26.     FD_SET(fd, &rds);

    27.     /*清除Buf*/
    28.     strcpy(Buf,"Buf is NULL!");
    29.     printf("Read BUF1: %s\n",Buf);

    30.     ret = select(fd + 1, &rds, NULL, NULL, NULL);
    31.     if (ret < 0)
    32.     {
    33.      printf("select error!\n");
    34.      exit(1);
    35.     }
    36.     if (FD_ISSET(fd, &rds))
    37.      read(fd, Buf, sizeof(Buf));           
    38.    
    39.     /*检测结果*/
    40.     printf("Read BUF2: %s\n",Buf);
    41.    
    42.     close(fd);
    43.    
    44.     return 0;   
    45. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值