字符设备驱动poll函数

长平狐 发布于 2012/09/03 12:46
阅读 395
收藏 0


    1. #ifndef _MEMDEV_H_
    2. #define _MEMDEV_H_

    3. #ifndef MEMDEV_MAJOR
    4. #define MEMDEV_MAJOR 0 /*预设的mem的主设备号*/
    5. #endif

    6. #ifndef MEMDEV_NR_DEVS
    7. #define MEMDEV_NR_DEVS 2 /*设备数*/
    8. #endif

    9. #ifndef MEMDEV_SIZE
    10. #define MEMDEV_SIZE 4096
    11. #endif

    12. /*mem设备描述结构体*/
    13. struct mem_dev 
    14. { 
    15.   char *data; 
    16.   unsigned long size; 
    17.   wait_queue_head_t inq; 
    18. };

    19. #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 (>= 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 (>= 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 -+ 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. }


原文链接:http://blog.csdn.net/hanchaoman/article/details/7333809
加载中
返回顶部
顶部