《操作系统》的实验代码。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

126 lines
2.8 KiB

12 years ago
  1. #include <defs.h>
  2. #include <stdio.h>
  3. #include <wait.h>
  4. #include <sync.h>
  5. #include <proc.h>
  6. #include <sched.h>
  7. #include <dev.h>
  8. #include <vfs.h>
  9. #include <iobuf.h>
  10. #include <inode.h>
  11. #include <unistd.h>
  12. #include <error.h>
  13. #include <assert.h>
  14. #define STDIN_BUFSIZE 4096
  15. static char stdin_buffer[STDIN_BUFSIZE];
  16. static off_t p_rpos, p_wpos;
  17. static wait_queue_t __wait_queue, *wait_queue = &__wait_queue;
  18. void
  19. dev_stdin_write(char c) {
  20. bool intr_flag;
  21. if (c != '\0') {
  22. local_intr_save(intr_flag);
  23. {
  24. stdin_buffer[p_wpos % STDIN_BUFSIZE] = c;
  25. if (p_wpos - p_rpos < STDIN_BUFSIZE) {
  26. p_wpos ++;
  27. }
  28. if (!wait_queue_empty(wait_queue)) {
  29. wakeup_queue(wait_queue, WT_KBD, 1);
  30. }
  31. }
  32. local_intr_restore(intr_flag);
  33. }
  34. }
  35. static int
  36. dev_stdin_read(char *buf, size_t len) {
  37. int ret = 0;
  38. bool intr_flag;
  39. local_intr_save(intr_flag);
  40. {
  41. for (; ret < len; ret ++, p_rpos ++) {
  42. try_again:
  43. if (p_rpos < p_wpos) {
  44. *buf ++ = stdin_buffer[p_rpos % STDIN_BUFSIZE];
  45. }
  46. else {
  47. wait_t __wait, *wait = &__wait;
  48. wait_current_set(wait_queue, wait, WT_KBD);
  49. local_intr_restore(intr_flag);
  50. schedule();
  51. local_intr_save(intr_flag);
  52. wait_current_del(wait_queue, wait);
  53. if (wait->wakeup_flags == WT_KBD) {
  54. goto try_again;
  55. }
  56. break;
  57. }
  58. }
  59. }
  60. local_intr_restore(intr_flag);
  61. return ret;
  62. }
  63. static int
  64. stdin_open(struct device *dev, uint32_t open_flags) {
  65. if (open_flags != O_RDONLY) {
  66. return -E_INVAL;
  67. }
  68. return 0;
  69. }
  70. static int
  71. stdin_close(struct device *dev) {
  72. return 0;
  73. }
  74. static int
  75. stdin_io(struct device *dev, struct iobuf *iob, bool write) {
  76. if (!write) {
  77. int ret;
  78. if ((ret = dev_stdin_read(iob->io_base, iob->io_resid)) > 0) {
  79. iob->io_resid -= ret;
  80. }
  81. return ret;
  82. }
  83. return -E_INVAL;
  84. }
  85. static int
  86. stdin_ioctl(struct device *dev, int op, void *data) {
  87. return -E_INVAL;
  88. }
  89. static void
  90. stdin_device_init(struct device *dev) {
  91. dev->d_blocks = 0;
  92. dev->d_blocksize = 1;
  93. dev->d_open = stdin_open;
  94. dev->d_close = stdin_close;
  95. dev->d_io = stdin_io;
  96. dev->d_ioctl = stdin_ioctl;
  97. p_rpos = p_wpos = 0;
  98. wait_queue_init(wait_queue);
  99. }
  100. void
  101. dev_init_stdin(void) {
  102. struct inode *node;
  103. if ((node = dev_create_inode()) == NULL) {
  104. panic("stdin: dev_create_node.\n");
  105. }
  106. stdin_device_init(vop_info(node, device));
  107. int ret;
  108. if ((ret = vfs_add_dev("stdin", node, 0)) != 0) {
  109. panic("stdin: vfs_add_dev: %e.\n", ret);
  110. }
  111. }