例:同时读取鼠标与键盘

传统情况下,由于阻塞只能同时读取一路。

解决方案

1.非阻塞IO

2.异步IO

3.IO多路复用

非阻塞IO

使用O_NONBLOCK和fcntl实现非阻塞

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


 int main()
{   
    int fd = -1;
    int flag = -1;
    int ret = -1;
    //把0号文件描述符(stdin)变为非阻塞
    flag = fcntl(0,F_GETFL);
    flag |= O_NONBLOCK;
    fcntl(0, F_SETFL, flag);//设置为非阻塞
     fd = open("/dev/input/mouse1", O_RDONLY|O_NONBLOCK);
    if(fd < 0)
    {
        perror("open");
        exit(-1);
    } 
    char buf[100];
    //读鼠标
    while(1)
    {
        memset(buf , 0, sizeof(buf));
        ret = read(fd , buf , 100);
        if(ret > 0)
        {
        printf("鼠标读取的内容:[%s]\n" , buf); 
        }
        memset(buf , 0, sizeof(buf));
        ret = read(0 , buf , 100);
        if(ret > 0)
        {
        printf("键盘读取的内容:[%s]\n" , buf);
        }
    }
    return 0;
}

异步IO

使用select和poll实现异步IO

特点为外部阻塞式,内部非阻塞式自动轮询多路阻塞式IO

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <poll.h>
int main(void)
{
    // 读取鼠标
    int fd = -1, ret = -1;
    char buf[200];
    struct pollfd myfds[2] = {0};
    
    fd = open("/dev/input/mouse1", O_RDONLY);
    if (fd < 0)
    {
        perror("open:");
        return -1;
    }
    
    // 初始化我们的pollfd
    myfds[0].fd = 0;            // 键盘
    myfds[0].events = POLLIN;    // 等待读操作
    
    myfds[1].fd = fd;            // 鼠标
    myfds[1].events = POLLIN;    // 等待读操作

    ret = poll(myfds, fd+1, 10000);
    if (ret < 0)
    {
        perror("poll: ");
        return -1;
    }
    else if (ret == 0)
    {
        printf("超时了\n");
    }
    else
    {
        // 等到了一路IO,然后去监测到底是哪个IO到了,处理之
        if (myfds[0].events == myfds[0].revents)
        {
            // 这里处理键盘
            memset(buf, 0, sizeof(buf));
            read(0, buf, 5);
            printf("键盘读出的内容是:[%s].\n", buf);
        }
        
        if (myfds[1].events == myfds[1].revents)
        {
            // 这里处理鼠标
            memset(buf, 0, sizeof(buf));
            read(fd, buf, 50);
            printf("鼠标读出的内容是:[%s].\n", buf);
        }
    }

    return 0;
}

异步IO

通过信号实现

异步IO的工作方法是:我们当前进程注册一个异步IO事件(使用signal注册一个信号SIGIO的处理函数),然后当前进程可以正常处理自己的事情,当异步事件发生后当前进程会收到一个SIGIO信号从而执行绑定的处理函数去处理这个异步事件。
涉及的函数:
(1)fcntl(F_GETFL、F_SETFL、O_ASYNC、F_SETOWN)
(2)signal或者sigaction(SIGIO)

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
int mousefd = -1;
// 绑定到SIGIO信号,在函数内处理异步通知事件 void func(int sig) { char buf[200] = {0}; if (sig != SIGIO) return; read(mousefd, buf, 50); printf("鼠标读出的内容是:[%s].\n", buf); } int main(void) { // 读取鼠标 char buf[200]; int flag = -1; mousefd = open("/dev/input/mouse1", O_RDONLY); if (mousefd < 0) { perror("open:"); return -1; } // 把鼠标的文件描述符设置为可以接受异步IO flag = fcntl(mousefd, F_GETFL); flag |= O_ASYNC; fcntl(mousefd, F_SETFL, flag); // 把异步IO事件的接收进程设置为当前进程 fcntl(mousefd, F_SETOWN, getpid()); // 注册当前进程的SIGIO信号捕获函数 signal(SIGIO, func); // 读键盘 while (1) { memset(buf, 0, sizeof(buf)); //printf("before 键盘 read.\n"); read(0, buf, 5); printf("键盘读出的内容是:[%s].\n", buf); } return 0; }

存储映射IO

1、mmap函数
2、LCD显示和IPC之共享内存
3、存储映射IO的特点
(1)共享而不是复制,减少内存操作
(2)处理大文件时效率高,小文件不划算

优质内容筛选与推荐>>
1、PHP验证码
2、js自动提示查询添加功能(不是自动补全)
3、斐波那契数列
4、C#面向对象
5、Apache配置完虚拟主机后,使用Chrome访问localhost还是默认目录htdocs


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn