pipe.c
上传用户:wudi5211
上传日期:2010-01-21
资源大小:607k
文件大小:10k
源码类别:

嵌入式Linux

开发平台:

C/C++

  1. /*
  2.  * pipe.c -- fifo driver for scull (v2.1)
  3.  *
  4.  */
  5.  
  6. #ifndef __KERNEL__
  7. #  define __KERNEL__
  8. #endif
  9. #ifndef MODULE
  10. #  define MODULE
  11. #endif
  12. #define __NO_VERSION__
  13. #include <linux/module.h> /* get MOD_DEC_USE_COUNT, not the version string */
  14. #include <linux/version.h> /* need it for conditionals in scull.h */
  15. #include <linux/kernel.h> /* printk() */
  16. #include <linux/malloc.h> /* kmalloc() */
  17. #include <linux/fs.h>     /* everything... */
  18. #include <linux/proc_fs.h>
  19. #include <linux/errno.h>  /* error codes */
  20. #include <linux/types.h>  /* size_t */
  21. #include <linux/fcntl.h>
  22. #include <asm/segment.h>  /* memcpy to/from fs */
  23. #include "scull.h"        /* local definitions */
  24. typedef struct Scull_Pipe {
  25.     struct wait_queue *inq, *outq;  /* read and write queues */
  26.     char *buffer, *end;             /* begin of buf, end of buf */
  27.     int buffersize;                 /* used in pointer arithmetic */
  28.     char *rp, *wp;                  /* where to read, where to write */
  29.     int nreaders, nwriters;         /* number of openings for r/w */
  30.     struct fasync_struct *async_queue; /* asynchronous readers */
  31. } Scull_Pipe;
  32. /*
  33.  * I don't use static symbols here, because register_symtab is called
  34.  */
  35. int scull_p_nr_devs =    SCULL_P_NR_DEVS;  /* number of pipe devices */
  36. int scull_p_buffer =  SCULL_P_BUFFER; /* buffer size */
  37. Scull_Pipe *scull_p_devices;
  38. /*
  39.  * Open and close
  40.  */
  41. int scull_p_open (struct inode *inode, struct file *filp)
  42. {
  43.     Scull_Pipe *dev;
  44.     int num = NUM(inode->i_rdev);
  45.     if (num >= scull_p_nr_devs) return -ENODEV;
  46.     dev = &scull_p_devices[num];
  47.     if (!dev->buffer) { /* allocate the buffer */
  48.         dev->buffer = kmalloc(scull_p_buffer, GFP_KERNEL);
  49.         if (!dev->buffer)
  50.             return -ENOMEM;
  51.     }
  52.     dev->buffersize = scull_p_buffer;
  53.     dev->end = dev->buffer + dev->buffersize;
  54.     dev->rp = dev->wp = dev->buffer; /* rd and wr from the beginning */
  55.     /* use f_mode,not  f_flags: it's cleaner (fs/open.c tells why) */
  56.     if (filp->f_mode & FMODE_READ)
  57.         dev->nreaders++;
  58.     if (filp->f_mode & FMODE_WRITE)
  59.         dev->nwriters++;
  60.     filp->private_data = dev;
  61.     MOD_INC_USE_COUNT;
  62.     return 0;
  63. }
  64. release_t scull_p_release (struct inode *inode, struct file *filp)
  65. {
  66.     Scull_Pipe *dev = filp->private_data;
  67.     int scull_p_fasync (struct inode *inode, struct file *filp, int mode);
  68.     /* remove this filp from the asynchronously notified filp's */
  69.     scull_p_fasync(inode, filp, 0);
  70.     if (filp->f_mode & FMODE_READ)
  71.         dev->nreaders--;
  72.     if (filp->f_mode & FMODE_WRITE)
  73.         dev->nwriters--;
  74.     if (dev->nreaders + dev->nwriters == 0) {
  75.         kfree(dev->buffer);
  76.         dev->buffer = NULL; /* the other fields are not checked on open */
  77.     }
  78.     MOD_DEC_USE_COUNT;
  79.     release_return(0);
  80. }
  81. /*
  82.  * Data management: read and write
  83.  */
  84. read_write_t scull_p_read (struct inode *inode, struct file *filp,
  85.                 char *buf, count_t count)
  86. {
  87.     Scull_Pipe *dev = filp->private_data;
  88.     while (dev->rp == dev->wp) { /* nothing to read */
  89.         if (filp->f_flags & O_NONBLOCK)
  90.             return -EAGAIN;
  91.         PDEBUG(""%s" reading: going to sleepn",current->comm);
  92.         interruptible_sleep_on(&dev->inq);
  93.         if (current->signal & ~current->blocked) /* a signal arrived */
  94.           return -ERESTARTSYS; /* tell the fs layer to handle it */
  95.         /* otherwise loop */
  96.     }
  97.     /* ok, data is there, return something */
  98.     if (dev->wp > dev->rp)
  99.         count = min(count, dev->wp - dev->rp);
  100.     else /* the write pointer has wrapped, return data up to dev->end */
  101.         count = min(count, dev->end - dev->rp);
  102.     copy_to_user(buf, dev->rp, count);
  103.     dev->rp += count;
  104.     if (dev->rp == dev->end)
  105.         dev->rp = dev->buffer; /* wrapped */
  106.     /* finally, awake any writers and return */
  107.     wake_up_interruptible(&dev->outq);
  108.     PDEBUG(""%s" did read %li bytesn",current->comm, (long)count);
  109.     return count;
  110. }
  111. read_write_t scull_p_write (struct inode *inode, struct file *filp,
  112.                 const char *buf, count_t count)
  113. {
  114.     Scull_Pipe *dev = filp->private_data;
  115.     /* left is the free space in the buffer, but it must be positive */
  116.     int left = (dev->rp + dev->buffersize - dev->wp) % dev->buffersize;
  117.     PDEBUG("write: left is %in",left);
  118.     while (left==1) { /* empty */
  119.         if (filp->f_flags & O_NONBLOCK)
  120.             return -EAGAIN;
  121.         PDEBUG(""%s" writing: going to sleepn",current->comm);
  122.         interruptible_sleep_on(&dev->outq);
  123.         if (current->signal & ~current->blocked) /* a signal arrived */
  124.           return -ERESTARTSYS; /* tell the fs layer to handle it */
  125.         /* otherwise loop, but recalculate free space */
  126.         left = (dev->rp + dev->buffersize - dev->wp) % dev->buffersize;
  127.     }
  128.     /* ok, space is there, accept something */
  129.     if (dev->wp >= dev->rp) {
  130.         count = min(count, dev->end - dev->wp); /* up to end-of-buffer */
  131.         if (count == left) /* leave a hole, even if at e-o-b */
  132.             count--;
  133.     }
  134.     else /* the write pointer has wrapped, fill up to rp-1 */
  135.         count = min(count, dev->rp - dev->wp - 1);
  136.     PDEBUG("Going to accept %li bytes to %p from %pn",
  137.            (long)count, dev->wp, buf);
  138.     copy_from_user(dev->wp, buf, count);
  139.     dev->wp += count;
  140.     if (dev->wp == dev->end)
  141.         dev ->wp = dev->buffer; /* wrapped */
  142.     /* finally, awake any reader */
  143.     wake_up_interruptible(&dev->inq);  /* blocked in read() and select() */
  144.     if (dev->async_queue)
  145.         kill_fasync (dev->async_queue, SIGIO); /* asynchronous readers */
  146.     PDEBUG(""%s" did write %li bytesn",current->comm, (long)count);
  147.     return count;
  148. }
  149. #ifdef __USE_OLD_SELECT__
  150. int scull_p_poll (struct inode *inode, struct file *filp,
  151.                   int mode, select_table *table)
  152. {
  153.     Scull_Pipe *dev = filp->private_data;
  154.     if (mode == SEL_IN) {
  155.         if (dev->rp != dev->wp) return 1; /* readable */
  156.         PDEBUG("Waiting to readn");
  157.         select_wait(&dev->inq, table); /* wait for data */
  158.         return 0;
  159.     }
  160.     if (mode == SEL_OUT) {
  161.         /*
  162.          * the buffer is full if "wp" is right behind "rp",
  163.          * and the buffer is circular. "left" can't drop
  164.          * to 0, as this would be taken as empty buffer
  165.          */
  166.         int left = (dev->rp + dev->buffersize - dev->wp) % dev->buffersize;
  167.         if (left>1) return 1; /* writable */
  168.         PDEBUG("Waiting to writen");
  169.         select_wait(&dev->outq, table); /* wait for free space */
  170.         return 0;
  171.     }
  172.     return 0; /* never exception-able */
  173. }
  174. #else /* the new poll interface */
  175. unsigned int scull_p_poll (struct file *filp, poll_table *wait)
  176. {
  177.     Scull_Pipe *dev = filp->private_data;
  178.     unsigned int mask = 0;
  179.     /* how many bytes left there to be read? */
  180.     int left = (dev->rp + dev->buffersize - dev->wp) % dev->buffersize;
  181.     poll_wait(&dev->inq,  wait);
  182.     poll_wait(&dev->outq, wait);
  183.     if (dev->rp != dev->wp) mask |= POLLIN | POLLRDNORM;  /* readable */
  184.     if (left)               mask |= POLLOUT | POLLWRNORM; /* writable */
  185.     return mask;
  186. }
  187. #endif
  188. int scull_p_fasync (struct inode *inode, struct file *filp, int mode)
  189. {
  190.     Scull_Pipe *dev = filp->private_data;
  191.     return fasync_helper(inode, filp, mode, &dev->async_queue);
  192. }
  193. lseek_t scull_p_lseek (struct inode *inode, struct file *filp,
  194.                  lseek_off_t off, int whence)
  195. {
  196.     return -ESPIPE; /* unseekable */
  197. }
  198. #ifdef SCULL_USE_PROC
  199. int scull_read_p_mem(char *buf, char **start, off_t offset,
  200.                    int len, int unused)
  201. {
  202.     int i;
  203.     Scull_Pipe *p;
  204.     #define LIMIT (PAGE_SIZE-200) /* don't print any more after this size */
  205.     len = sprintf(buf, "Default buffersize is %in", scull_p_buffer);
  206.     for(i = 0; i<scull_p_nr_devs; i++) {
  207.         if (len > LIMIT) break;
  208.         p = &scull_p_devices[i];
  209.         len += sprintf(buf+len, "nDevice %i: %pn", i, p);
  210.         len += sprintf(buf+len, "   Queues: %p %pn", p->inq, p->outq);
  211.         len += sprintf(buf+len, "   Buffer: %p to %p (%i bytes)n",
  212.                        p->buffer, p->end, p->buffersize);
  213.         len += sprintf(buf+len, "   rp %p   wp %pn", p->rp, p->wp);
  214.         len += sprintf(buf+len, "   readers %i   writers %in",
  215.                        p->nreaders, p->nwriters);
  216.     }
  217.     return len;
  218. }
  219. struct proc_dir_entry scull_proc_p_entry = {
  220.         0,                 /* low_ino: the inode -- dynamic */
  221.         9, "scullpipe",     /* len of name and name */
  222.         S_IFREG | S_IRUGO, /* mode */
  223.         1, 0, 0,           /* nlinks, owner, group */
  224.         0, NULL,           /* size - unused; operations -- use default */
  225.         &scull_read_p_mem,   /* function used to read data */
  226.         /* nothing more */
  227.     };
  228. #endif
  229. /*
  230.  * The file operations for the pipe device
  231.  * (some are overlayed with bare scull)
  232.  */
  233. struct file_operations scull_pipe_fops = {
  234.     scull_p_lseek,
  235.     scull_p_read,
  236.     scull_p_write,
  237.     NULL,          /* scull_p_readdir */
  238.     scull_p_poll,
  239.     scull_ioctl,
  240.     NULL,          /* scull_p_mmap */
  241.     scull_p_open,
  242.     scull_p_release,
  243.     NULL,          /* scull_p_fsync */
  244.     scull_p_fasync,
  245.                    /* nothing more, fill with NULLs */
  246. };
  247. int scull_p_init(void)
  248. {
  249.     scull_p_devices = kmalloc(scull_p_nr_devs * sizeof(Scull_Pipe),
  250.                               GFP_KERNEL);
  251.     if (scull_p_devices == NULL)
  252.         return -ENOMEM;
  253.     memset(scull_p_devices, 0, scull_p_nr_devs * sizeof(Scull_Pipe));
  254. #ifdef SCULL_USE_PROC
  255.     proc_register_dynamic(&proc_root, &scull_proc_p_entry);
  256. #endif
  257.     return 0;
  258. }
  259. void scull_p_cleanup(void) /* called by cleanup_module */
  260. {
  261.     int i;
  262.     for (i=0; i < scull_p_nr_devs; i++) {
  263.         if (scull_p_devices[i].buffer)
  264.             kfree(scull_p_devices[i].buffer);
  265.     }
  266.     kfree(scull_p_devices);
  267. #ifdef SCULL_USE_PROC
  268.     proc_unregister(&proc_root, scull_proc_p_entry.low_ino);
  269. #endif
  270.     return;
  271. }