fifo.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:3k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/fs/fifo.c
  3.  *
  4.  *  written by Paul H. Hargrove
  5.  *
  6.  *  Fixes:
  7.  * 10-06-1999, AV: fixed OOM handling in fifo_open(), moved
  8.  * initialization there, switched to external
  9.  * allocation of pipe_inode_info.
  10.  */
  11. #include <linux/mm.h>
  12. #include <linux/slab.h>
  13. #include <linux/smp_lock.h>
  14. static void wait_for_partner(struct inode* inode, unsigned int* cnt)
  15. {
  16. int cur = *cnt;
  17. while(cur == *cnt) {
  18. pipe_wait(inode);
  19. if(signal_pending(current))
  20. break;
  21. }
  22. }
  23. static void wake_up_partner(struct inode* inode)
  24. {
  25. wake_up_interruptible(PIPE_WAIT(*inode));
  26. }
  27. static int fifo_open(struct inode *inode, struct file *filp)
  28. {
  29. int ret;
  30. ret = -ERESTARTSYS;
  31. lock_kernel();
  32. if (down_interruptible(PIPE_SEM(*inode)))
  33. goto err_nolock_nocleanup;
  34. if (!inode->i_pipe) {
  35. ret = -ENOMEM;
  36. if(!pipe_new(inode))
  37. goto err_nocleanup;
  38. }
  39. filp->f_version = 0;
  40. switch (filp->f_mode) {
  41. case 1:
  42. /*
  43.  *  O_RDONLY
  44.  *  POSIX.1 says that O_NONBLOCK means return with the FIFO
  45.  *  opened, even when there is no process writing the FIFO.
  46.  */
  47. filp->f_op = &read_fifo_fops;
  48. PIPE_RCOUNTER(*inode)++;
  49. if (PIPE_READERS(*inode)++ == 0)
  50. wake_up_partner(inode);
  51. if (!PIPE_WRITERS(*inode)) {
  52. if ((filp->f_flags & O_NONBLOCK)) {
  53. /* suppress POLLHUP until we have
  54.  * seen a writer */
  55. filp->f_version = PIPE_WCOUNTER(*inode);
  56. } else 
  57. {
  58. wait_for_partner(inode, &PIPE_WCOUNTER(*inode));
  59. if(signal_pending(current))
  60. goto err_rd;
  61. }
  62. }
  63. break;
  64. case 2:
  65. /*
  66.  *  O_WRONLY
  67.  *  POSIX.1 says that O_NONBLOCK means return -1 with
  68.  *  errno=ENXIO when there is no process reading the FIFO.
  69.  */
  70. ret = -ENXIO;
  71. if ((filp->f_flags & O_NONBLOCK) && !PIPE_READERS(*inode))
  72. goto err;
  73. filp->f_op = &write_fifo_fops;
  74. PIPE_WCOUNTER(*inode)++;
  75. if (!PIPE_WRITERS(*inode)++)
  76. wake_up_partner(inode);
  77. if (!PIPE_READERS(*inode)) {
  78. wait_for_partner(inode, &PIPE_RCOUNTER(*inode));
  79. if (signal_pending(current))
  80. goto err_wr;
  81. }
  82. break;
  83. case 3:
  84. /*
  85.  *  O_RDWR
  86.  *  POSIX.1 leaves this case "undefined" when O_NONBLOCK is set.
  87.  *  This implementation will NEVER block on a O_RDWR open, since
  88.  *  the process can at least talk to itself.
  89.  */
  90. filp->f_op = &rdwr_fifo_fops;
  91. PIPE_READERS(*inode)++;
  92. PIPE_WRITERS(*inode)++;
  93. PIPE_RCOUNTER(*inode)++;
  94. PIPE_WCOUNTER(*inode)++;
  95. if (PIPE_READERS(*inode) == 1 || PIPE_WRITERS(*inode) == 1)
  96. wake_up_partner(inode);
  97. break;
  98. default:
  99. ret = -EINVAL;
  100. goto err;
  101. }
  102. /* Ok! */
  103. up(PIPE_SEM(*inode));
  104. unlock_kernel();
  105. return 0;
  106. err_rd:
  107. if (!--PIPE_READERS(*inode))
  108. wake_up_interruptible(PIPE_WAIT(*inode));
  109. ret = -ERESTARTSYS;
  110. goto err;
  111. err_wr:
  112. if (!--PIPE_WRITERS(*inode))
  113. wake_up_interruptible(PIPE_WAIT(*inode));
  114. ret = -ERESTARTSYS;
  115. goto err;
  116. err:
  117. if (!PIPE_READERS(*inode) && !PIPE_WRITERS(*inode)) {
  118. struct pipe_inode_info *info = inode->i_pipe;
  119. inode->i_pipe = NULL;
  120. free_page((unsigned long)info->base);
  121. kfree(info);
  122. }
  123. err_nocleanup:
  124. up(PIPE_SEM(*inode));
  125. err_nolock_nocleanup:
  126. unlock_kernel();
  127. return ret;
  128. }
  129. /*
  130.  * Dummy default file-operations: the only thing this does
  131.  * is contain the open that then fills in the correct operations
  132.  * depending on the access mode of the file...
  133.  */
  134. struct file_operations def_fifo_fops = {
  135. open: fifo_open, /* will set read or write pipe_fops */
  136. };