Previous Next Contents

5.5  高级 I/O

5.5.1  Linux 中直接的 I/O 端口读写

===============================================================================
       #include <unistd.h> /* for libc5 */
       #include <sys/io.h> /* for glibc */
       
       int  ioperm (unsigned  long  from,  unsigned  long num, int turn_on);
       int  iopl (int level);
-------------------------------------------------------------------------------
EXAMPLE:
       /* get PC speak I/O ports access permission 
          and implement a beep function */

        #define COUNTER_ADDR    0x61

        int beepCount = 500000;

        BOOL InitIOPerm ()
        {
            if (ioperm (COUNTER_ADDR, 1, TRUE)) {
                fprintf (stderr, "Can not get beep I/O permission!\n");
                return FALSE;
            }

            return TRUE;
        }

        void CleanupIOPerm ()
        {
            ioperm (COUNTER_ADDR, 1, FALSE);
        }

        void GUIAPI Beep (void)
        {
            outb (inb (COUNTER_ADDR) | 3, COUNTER_ADDR);
            usleep (beepCount);
            outb (inb (COUNTER_ADDR) & 0xFC, COUNTER_ADDR);
        }
===============================================================================

5.5.2  记录锁定

5.5.3  非阻塞 I/O

5.5.4  I/O 多工

===============================================================================
       #include <sys/time.h>
       #include <sys/types.h>
       #include <unistd.h>

       int  select (int n,  fd_set  *readfds,  fd_set  *writefds,
                    fd_set *exceptfds, struct timeval *timeout);

       FD_CLR (int fd, fd_set *set);
       FD_ISSET (int fd, fd_set *set);
       FD_SET (int fd, fd_set *set);
       FD_ZERO (fd_set *set);

       #include 

       int poll(struct pollfd *ufds, unsigned int nfds, int timeout);
-------------------------------------------------------------------------------
               struct pollfd {
                       int fd;           /* file descriptor */
                       short events;     /* requested events */
                       short revents;    /* returned events */
               };
-------------------------------------------------------------------------------
   * select 中的 n 是所等待文件描述符中最大的值加 1.
-------------------------------------------------------------------------------
EXAMPLE 1:
       /* 在 Virtual Console on MiniGUI 中, 我们用 poll 等待主伪终端上的数据 */

        void ReadMasterPty (PCONINFO con)
        {
            BYTE buff [BUFSIZ + 1];
            int nRead;
            struct pollfd fd = {con->masterPty, POLLIN, 0};
            int ret;

            ret = poll (&fd, 1, 10);   // about 0.01s

            if (ret == 0) {
                return;
            }
            else if (ret > 0) {
                if ((nRead = read (con->masterPty, buff, BUFSIZ)) > 0) {
                    VtWrite (con, buff, nRead);
                    TextRefresh (con, true);
                }
            }
        }

       /* 如果没有数据, 我们处理 MiniGUI 的消息, 包括键盘和鼠标事件 */

            ...

            // Enter message loop.
            do {
                // It is time to read from master pty, and output.
                ReadMasterPty (pConInfo);

                if (pConInfo->terminate)
                    break;

                while (HavePendingMessage (hMainWnd)) {
                    if (!GetMessage (&Msg, hMainWnd))
                        break;
                    DispatchMessage (&Msg);
                }

            } while (TRUE);

            ...

       /* 我们也可以用非阻塞 I/O 实现 ReadMasterPty, 但这种方法非常消耗 CPU 资源 */

-------------------------------------------------------------------------------
EXAMPLE 1:
       /* SVGALib 用 select 函数实现 vga_waitevent 函数等待键盘和鼠标事件 */

        int vga_waitevent(int which, fd_set * in, fd_set * out, fd_set * except,
                          struct timeval *timeout)
        {
            fd_set infdset;
            int fd, retval;

            if (!in) {
                in = &infdset;
                FD_ZERO(in);
            }
            fd = __svgalib_mouse_fd;        /* __svgalib_mouse_fd might change on
                                           vc switch!! */
            if ((which & VGA_MOUSEEVENT) && (fd >= 0))
                FD_SET(fd, in);
            if (which & VGA_KEYEVENT) {
                fd = __svgalib_kbd_fd;
                if (fd >= 0) {                /* we are in raw mode */
                    FD_SET(fd, in);
                } else {
                    FD_SET(__svgalib_tty_fd, in);
                }
            }
            if (select(FD_SETSIZE, in, out, except, timeout) < 0)
                return -1;
            retval = 0;
            fd = __svgalib_mouse_fd;
            if ((which & VGA_MOUSEEVENT) && (fd >= 0)) {
                if (FD_ISSET(fd, in)) {
                    retval |= VGA_MOUSEEVENT;
                    FD_CLR(fd, in);
                    mouse_update();
                }
            }
            if (which & VGA_KEYEVENT) {
                fd = __svgalib_kbd_fd;
                if (fd >= 0) {                /* we are in raw mode */
                    if (FD_ISSET(fd, in)) {
                        FD_CLR(fd, in);
                        retval |= VGA_KEYEVENT;
                        keyboard_update();
                    }
                } else if (FD_ISSET(__svgalib_tty_fd, in)) {
                    FD_CLR(__svgalib_tty_fd, in);
                    retval |= VGA_KEYEVENT;
                }
            }
            return retval;
        }
===============================================================================

5.5.4  异步 I/O

5.5.5  内存映射





Previous Next Contents