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

嵌入式Linux

开发平台:

C/C++

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