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

嵌入式Linux

开发平台:

C/C++

  1. /*
  2.  * pipe.c -- fifo driver for scull
  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> /* needed for the 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 "scull.h"        /* local definitions and sysdep.h */
  23. #ifndef min
  24. #  define min(a,b) ((a)<(b) ? (a) : (b)) /* we use it in this file */
  25. #endif
  26. typedef struct Scull_Pipe {
  27.     wait_queue_head_t inq, outq;    /* read and write queues */
  28.     char *buffer, *end;             /* begin of buf, end of buf */
  29.     int buffersize;                 /* used in pointer arithmetic */
  30.     char *rp, *wp;                  /* where to read, where to write */
  31.     int nreaders, nwriters;         /* number of openings for r/w */
  32.     struct fasync_struct *async_queue; /* asynchronous readers */
  33.     struct semaphore sem;           /* mutual exclusion semaphore */
  34.     devfs_handle_t handle;         /* only used if devfs is there */
  35. } Scull_Pipe;
  36. /* parameters */
  37. int scull_p_nr_devs = SCULL_P_NR_DEVS;  /* number of pipe devices */
  38. int scull_p_buffer =  SCULL_P_BUFFER;   /* buffer size */
  39. MODULE_PARM(scull_p_nr_devs,"i");
  40. MODULE_PARM(scull_p_buffer,"i");
  41. Scull_Pipe *scull_p_devices;
  42. /*
  43.  * Open and close
  44.  */
  45. int scull_p_open(struct inode *inode, struct file *filp)
  46. {
  47.     Scull_Pipe *dev;
  48.     int num = NUM(inode->i_rdev);
  49.     if (!filp->private_data) {
  50.         if (num >= scull_p_nr_devs) return -ENODEV;
  51.         dev = &scull_p_devices[num];
  52.         filp->private_data = dev;
  53.     } else {
  54.         dev = filp->private_data;
  55.     }
  56.     if (down_interruptible(&dev->sem))
  57.         return -ERESTARTSYS;
  58.     if (!dev->buffer) { /* allocate the buffer */
  59.         dev->buffer = kmalloc(scull_p_buffer, GFP_KERNEL);
  60.         if (!dev->buffer) {
  61.             up(&dev->sem);
  62.             return -ENOMEM;
  63.         }
  64.     }
  65.     dev->buffersize = scull_p_buffer;
  66.     dev->end = dev->buffer + dev->buffersize;
  67.     dev->rp = dev->wp = dev->buffer; /* rd and wr from the beginning */
  68.     /* use f_mode,not  f_flags: it's cleaner (fs/open.c tells why) */
  69.     if (filp->f_mode & FMODE_READ)
  70.         dev->nreaders++;
  71.     if (filp->f_mode & FMODE_WRITE)
  72.         dev->nwriters++;
  73.     up(&dev->sem);
  74.     
  75.     filp->private_data = dev;
  76.     MOD_INC_USE_COUNT;
  77.     return 0;
  78. }
  79. int scull_p_release(struct inode *inode, struct file *filp)
  80. {
  81.     Scull_Pipe *dev = filp->private_data;
  82.     int scull_p_fasync(fasync_file fd, struct file *filp, int mode);
  83. #ifdef LINUX_20
  84.     scull_p_fasync(inode, filp, 0);
  85. #else
  86.     /* remove this filp from the asynchronously notified filp's */
  87.     scull_p_fasync(-1, filp, 0);
  88. #endif
  89.     down(&dev->sem);
  90.     if (filp->f_mode & FMODE_READ)
  91.         dev->nreaders--;
  92.     if (filp->f_mode & FMODE_WRITE)
  93.         dev->nwriters--;
  94.     if (dev->nreaders + dev->nwriters == 0) {
  95.         kfree(dev->buffer);
  96.         dev->buffer = NULL; /* the other fields are not checked on open */
  97.     }
  98.     up(&dev->sem);
  99.     MOD_DEC_USE_COUNT;
  100.     return 0;
  101. }
  102. /*
  103.  * Data management: read and write
  104.  */
  105. ssize_t scull_p_read (struct file *filp, char *buf, size_t count,
  106.                 loff_t *f_pos)
  107. {
  108.     Scull_Pipe *dev = filp->private_data;
  109.     if (f_pos != &filp->f_pos) return -ESPIPE;
  110.     if (down_interruptible(&dev->sem))
  111.         return -ERESTARTSYS;
  112.     while (dev->rp == dev->wp) { /* nothing to read */
  113.         up(&dev->sem); /* release the lock */
  114.         if (filp->f_flags & O_NONBLOCK)
  115.             return -EAGAIN;
  116.         PDEBUG(""%s" reading: going to sleepn", current->comm);
  117.         if (wait_event_interruptible(dev->inq, (dev->rp != dev->wp)))
  118.             return -ERESTARTSYS; /* signal: tell the fs layer to handle it */
  119.         /* otherwise loop, but first reacquire the lock */
  120.         if (down_interruptible(&dev->sem))
  121.             return -ERESTARTSYS;
  122.     }
  123.     /* ok, data is there, return something */
  124.     if (dev->wp > dev->rp)
  125.         count = min(count, dev->wp - dev->rp);
  126.     else /* the write pointer has wrapped, return data up to dev->end */
  127.         count = min(count, dev->end - dev->rp);
  128.     if (copy_to_user(buf, dev->rp, count)) {
  129.         up (&dev->sem);
  130.         return -EFAULT;
  131.     }
  132.     dev->rp += count;
  133.     if (dev->rp == dev->end)
  134.         dev->rp = dev->buffer; /* wrapped */
  135.     up (&dev->sem);
  136.     /* finally, awake any writers and return */
  137.     wake_up_interruptible(&dev->outq);
  138.     PDEBUG(""%s" did read %li bytesn",current->comm, (long)count);
  139.     return count;
  140. }
  141. static inline int spacefree(Scull_Pipe *dev)
  142. {
  143.     if (dev->rp == dev->wp)
  144.         return dev->buffersize - 1;
  145.     return ((dev->rp + dev->buffersize - dev->wp) % dev->buffersize) - 1;
  146. }
  147. ssize_t scull_p_write(struct file *filp, const char *buf, size_t count,
  148.                 loff_t *f_pos)
  149. {
  150.     Scull_Pipe *dev = filp->private_data;
  151.     
  152.     if (f_pos != &filp->f_pos) return -ESPIPE;
  153.     if (down_interruptible(&dev->sem))
  154.         return -ERESTARTSYS;
  155.     
  156.     /* Make sure there's space to write */
  157.     while (spacefree(dev) == 0) { /* full */
  158.         up(&dev->sem);
  159.         if (filp->f_flags & O_NONBLOCK)
  160.             return -EAGAIN;
  161.         PDEBUG(""%s" writing: going to sleepn",current->comm);
  162.         if (wait_event_interruptible(dev->outq, spacefree(dev) > 0))
  163.             return -ERESTARTSYS; /* signal: tell the fs layer to handle it */
  164.         if (down_interruptible(&dev->sem))
  165.             return -ERESTARTSYS;
  166.     }
  167.     /* ok, space is there, accept something */
  168.     count = min(count, spacefree(dev));
  169.     if (dev->wp >= dev->rp)
  170.         count = min(count, dev->end - dev->wp); /* up to end-of-buffer */
  171.     else /* the write pointer has wrapped, fill up to rp-1 */
  172.         count = min(count, dev->rp - dev->wp - 1);
  173.     PDEBUG("Going to accept %li bytes to %p from %pn",
  174.            (long)count, dev->wp, buf);
  175.     if (copy_from_user(dev->wp, buf, count)) {
  176.         up (&dev->sem);
  177.         return -EFAULT;
  178.     }
  179.     dev->wp += count;
  180.     if (dev->wp == dev->end)
  181.         dev->wp = dev->buffer; /* wrapped */
  182.     up(&dev->sem);
  183.     /* finally, awake any reader */
  184.     wake_up_interruptible(&dev->inq);  /* blocked in read() and select() */
  185.     /* and signal asynchronous readers, explained late in chapter 5 */
  186.     if (dev->async_queue)
  187.         kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
  188.     PDEBUG(""%s" did write %li bytesn",current->comm, (long)count);
  189.     return count;
  190. }
  191. #ifdef __USE_OLD_SELECT__
  192. int scull_p_poll(struct inode *inode, struct file *filp,
  193.                   int mode, select_table *table)
  194. {
  195.     Scull_Pipe *dev = filp->private_data;
  196.     if (mode == SEL_IN) {
  197.         if (dev->rp != dev->wp) return 1; /* readable */
  198.         PDEBUG("Waiting to readn");
  199.         select_wait(&dev->inq, table); /* wait for data */
  200.         return 0;
  201.     }
  202.     if (mode == SEL_OUT) {
  203.         /*
  204.          * The buffer is circular; it is considered full
  205.          * if "wp" is right behind "rp". "left" is 0 if the
  206.          * buffer is empty, and it is "1" if it is completely full.
  207.          */
  208.         int left = (dev->rp + dev->buffersize - dev->wp) % dev->buffersize;
  209.         if (left != 1) return 1; /* writable */
  210.         PDEBUG("Waiting to writen");
  211.         select_wait(&dev->outq, table); /* wait for free space */
  212.         return 0;
  213.     }
  214.     return 0; /* never exception-able */
  215. }
  216. #else /* Use poll instead, already shown */
  217. unsigned int scull_p_poll(struct file *filp, poll_table *wait)
  218. {
  219.     Scull_Pipe *dev = filp->private_data;
  220.     unsigned int mask = 0;
  221.     /*
  222.      * The buffer is circular; it is considered full
  223.      * if "wp" is right behind "rp". "left" is 0 if the
  224.      * buffer is empty, and it is "1" if it is completely full.
  225.      */
  226.     int left = (dev->rp + dev->buffersize - dev->wp) % dev->buffersize;
  227.     poll_wait(filp, &dev->inq,  wait);
  228.     poll_wait(filp, &dev->outq, wait);
  229.     if (dev->rp != dev->wp) mask |= POLLIN | POLLRDNORM;  /* readable */
  230.     if (left != 1)          mask |= POLLOUT | POLLWRNORM; /* writable */
  231.     return mask;
  232. }
  233. #endif
  234. int scull_p_fasync(fasync_file fd, struct file *filp, int mode)
  235. {
  236.     Scull_Pipe *dev = filp->private_data;
  237.     return fasync_helper(fd, filp, mode, &dev->async_queue);
  238. }
  239. loff_t scull_p_llseek(struct file *filp,  loff_t off, int whence)
  240. {
  241.     return -ESPIPE; /* unseekable */
  242. }
  243. #ifdef SCULL_DEBUG
  244. void scullp_proc_offset(char *buf, char **start, off_t *offset, int *len)
  245. {
  246.     if (*offset == 0)
  247.         return;
  248.     if (*offset >= *len) {      /* Not there yet */
  249.         *offset -= *len;
  250.         *len = 0;
  251.     }
  252.     else {                      /* We're into the interesting stuff now */
  253.         *start = buf + *offset;
  254.         *offset = 0;
  255.     }
  256. }
  257. int scull_read_p_mem(char *buf, char **start, off_t offset,
  258.                    int count, int *eof, void *data)
  259. {
  260.     int i, len;
  261.     Scull_Pipe *p;
  262.     #define LIMIT (PAGE_SIZE-200) /* don't print any more after this size */
  263.     *start = buf;
  264.     len = sprintf(buf, "Default buffersize is %in", scull_p_buffer);
  265.     for(i = 0; i<scull_p_nr_devs && len <= LIMIT; i++) {
  266.         p = &scull_p_devices[i];
  267.         if (down_interruptible(&p->sem))
  268.             return -ERESTARTSYS;
  269.         len += sprintf(buf+len, "nDevice %i: %pn", i, p);
  270. /*        len += sprintf(buf+len, "   Queues: %p %pn", p->inq, p->outq);*/
  271.         len += sprintf(buf+len, "   Buffer: %p to %p (%i bytes)n",
  272.                        p->buffer, p->end, p->buffersize);
  273.         len += sprintf(buf+len, "   rp %p   wp %pn", p->rp, p->wp);
  274.         len += sprintf(buf+len, "   readers %i   writers %in",
  275.                        p->nreaders, p->nwriters);
  276.         up(&p->sem);
  277.         scullp_proc_offset(buf, start, &offset, &len);
  278.     }
  279.     *eof = (len <= LIMIT);
  280.     return len;
  281. }
  282. #ifdef USE_PROC_REGISTER
  283. static int scull_p_get_info(char *buf, char **start, off_t offset, int len,
  284.                 int unused)
  285. {
  286.     int eof = 0;
  287.     return scull_read_p_mem(buf, start, offset, len, &eof, NULL);
  288. }
  289. struct proc_dir_entry scull_proc_p_entry = {
  290.         0,                  /* low_ino: the inode -- dynamic */
  291.         9, "scullpipe",     /* len of name and name */
  292.         S_IFREG | S_IRUGO,  /* mode */
  293.         1, 0, 0,            /* nlinks, owner, group */
  294.         0, NULL,            /* size - unused; operations -- use default */
  295.         &scull_p_get_info,  /* function used to read data */
  296.         /* nothing more */
  297.     };
  298. static inline void create_proc_read_entry(const char *name, mode_t mode,
  299.                 struct proc_dir_entry *base, void *read_func, void *data)
  300. {
  301.     proc_register_dynamic(&proc_root, &scull_proc_p_entry);
  302. }
  303. static inline void remove_proc_entry(char *name, void *parent)
  304. {
  305.     proc_unregister(&proc_root, scull_proc_p_entry.low_ino);
  306. }
  307. #endif /* USE_PROC_REGISTER */
  308. #endif
  309. /*
  310.  * 2.0 wrappers
  311.  */
  312. #ifdef LINUX_20
  313. static int scull_p_lseek_20(struct inode *ino, struct file *f,
  314.                 off_t offset, int whence)
  315. {
  316.     return (int)scull_p_llseek(f, offset, whence);
  317. }
  318. int scull_p_read_20(struct inode *ino, struct file *f, char *buf, int count)
  319. {
  320.     return (int)scull_p_read(f, buf, count, &f->f_pos);
  321. }
  322. int scull_p_write_20(struct inode *ino, struct file *f, const char *b, int c)
  323. {
  324.     return (int)scull_p_write(f, b, c, &f->f_pos);
  325. }
  326. void scull_p_release_20(struct inode *ino, struct file *f)
  327. {
  328.     scull_p_release(ino, f);
  329. }
  330. #define scull_p_llseek scull_p_lseek_20
  331. #define scull_p_read scull_p_read_20
  332. #define scull_p_write scull_p_write_20
  333. #define scull_p_release scull_p_release_20
  334. #define llseek lseek
  335. #define poll select
  336. #endif
  337. /*
  338.  * The file operations for the pipe device
  339.  * (some are overlayed with bare scull)
  340.  */
  341. struct file_operations scull_pipe_fops = {
  342.     llseek:     scull_p_llseek,
  343.     read:       scull_p_read,
  344.     write:      scull_p_write,
  345.     poll:       scull_p_poll,
  346.     ioctl:      scull_ioctl,
  347.     open:       scull_p_open,
  348.     release:    scull_p_release,
  349.     fasync:     scull_p_fasync,
  350. };
  351. char pipename[8]; /* only used for devfs names */
  352. int scull_p_init(void)
  353. {
  354.     int i;
  355.     SET_MODULE_OWNER(&scull_pipe_fops);
  356.     scull_p_devices = kmalloc(scull_p_nr_devs * sizeof(Scull_Pipe),
  357.                               GFP_KERNEL);
  358.     if (scull_p_devices == NULL)
  359.         return -ENOMEM;
  360.     memset(scull_p_devices, 0, scull_p_nr_devs * sizeof(Scull_Pipe));
  361.     for (i = 0; i < scull_p_nr_devs; i++) {
  362.         init_waitqueue_head(&(scull_p_devices[i].inq));
  363.         init_waitqueue_head(&(scull_p_devices[i].outq));
  364.         sema_init(&scull_p_devices[i].sem, 1);
  365. #ifdef CONFIG_DEVFS_FS
  366.         sprintf(pipename, "pipe%i", i);
  367.         scull_p_devices[i].handle =
  368.             devfs_register(scull_devfs_dir, pipename,
  369.                            DEVFS_FL_AUTO_DEVNUM,
  370.                            0, 0, S_IFCHR | S_IRUGO | S_IWUGO,
  371.                            &scull_pipe_fops,
  372.                            scull_p_devices + i);
  373.         if (!scull_p_devices[i].handle) {
  374.             /* ignore errors, at worse we have less devices */
  375.             printk(KERN_WARNING
  376.                    "scull: can't register pipe device nr. %in", i);
  377.         }
  378. #endif
  379.     }
  380. #ifdef SCULL_DEBUG
  381.     create_proc_read_entry("scullpipe", 0, NULL, scull_read_p_mem, NULL);
  382. #endif
  383.     return 0;
  384. }
  385. /*
  386.  * This is called by cleanup_module or on failure.
  387.  * It is required to never fail, even if nothing was initialized first
  388.  */
  389. void scull_p_cleanup(void)
  390. {
  391.     int i;
  392. #ifdef SCULL_DEBUG
  393.     remove_proc_entry("scullpipe", 0);
  394. #endif
  395.     if (!scull_p_devices) return; /* nothing else to release */
  396.     for (i=0; i < scull_p_nr_devs; i++) {
  397.         if (scull_p_devices[i].buffer)
  398.             kfree(scull_p_devices[i].buffer);
  399.         devfs_unregister(scull_p_devices[i].handle);
  400.     }
  401.     kfree(scull_p_devices);
  402.     scull_p_devices = NULL; /* pedantic */
  403.     return;
  404. }