阻塞IO与非阻塞IO

阻塞IO,
当前进程因不满足一些条件,而被挂起,即阻塞,cpu改去服务其它进程,
read一个普通文件,就马上执行,read一个鼠标,可是鼠标没有动,于是就阻塞了,
阻塞的好处,
利于os性能的发挥,cpu发挥高,虽然个体的费了点时间,但是总的效率得到了提高,

阻塞在多路IO的时候,缺陷就出来了,比如2路IO分别要读键盘和鼠标,阻塞在鼠标,可是鼠标没动,然后键盘输入也没用,
非阻塞IO,如果涉及多路IO,最好就不要用阻塞IO,
默认都是阻塞方式,
实现非阻塞,
1,打开文件O_NONBLOCK,
2,fcntl函数,

阻塞式IO的困境

读取键盘,标准输入,stdin,0,默认就是打开的,
read( 0, buf, 2 );

读取鼠标,
int fd = -1;
fd = open( “/dev/input/mouse1”, O_RDONLY );
read( fd, buf, 5 );

同时读取键盘和鼠标,
由于读取2者,都是阻塞方式的,
而且程序中有固有的先后顺序,我们需要配合,比如先动鼠标,然后动键盘,

阻塞有它的好处,也有它的不便之处,

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

int main(void)  
{  
    // 读取鼠标  
    int fd = -1;  
    char buf[200];  

    fd = open("/dev/input/mouse1", O_RDONLY);  
    if (fd < 0)  
    {  
        perror("open:");  
        return -1;  
    }  

    memset(buf, 0, sizeof(buf));  
    printf("before 鼠标 read.\n");  
    read(fd, buf, 50);  
    printf("鼠标读出的内容是:[%s].\n", buf);  


    // 读键盘  
    memset(buf, 0, sizeof(buf));  
    printf("before 键盘 read.\n");  
    read(0, buf, 5);  
    printf("键盘读出的内容是:[%s].\n", buf);  


    return 0;  
} 

非阻塞IO,如果没有读到东西,就立即返回,

改变标准输入为非阻塞式的,
flag = fcntl( 0, F_GETFL );
flag |= O_NONBLOCK;
fcntl( 0, F_SETFL, flag );

非阻塞打开鼠标,
fd = open( “/dev/input/mouse1”, O_RDONLY | O_NONBLOCK );

然后出现了一种结果,
从鼠标和键盘所读出的内容都是空的,因为来不及输入,

接着,做了一种改变,
把读鼠标和键盘放到一个while(1)中,
经过这次修改,结果看起来舒服多了

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



int main(void)  
{  
    // 读取鼠标  
    int fd = -1;  
    int flag = -1;  
    char buf[200];  
    int ret = -1;  

    fd = open("/dev/input/mouse1", O_RDONLY | O_NONBLOCK);  
    if (fd < 0)  
    {  
        perror("open:");  
        return -1;  
    }  

    // 把0号文件描述符(stdin)变成非阻塞式的  
    flag = fcntl(0, F_GETFL);       // 先获取原来的flag  
    flag |= O_NONBLOCK;             // 添加非阻塞属性  
    fcntl(0, F_SETFL, flag);        // 更新flag  
    // 这3步之后,0就变成了非阻塞式的了  

    while (1)  
    {  
        // 读鼠标  
        memset(buf, 0, sizeof(buf));  
        //printf("before 鼠标 read.\n");  
        ret = read(fd, buf, 50);  
        if (ret > 0)  
        {  
            printf("鼠标读出的内容是:[%s].\n", buf);  
        }  

        // 读键盘  
        memset(buf, 0, sizeof(buf));  
        //printf("before 键盘 read.\n");  
        ret = read(0, buf, 5);  
        if (ret > 0)  
        {  
            printf("键盘读出的内容是:[%s].\n", buf);  
        }  
    }  

    return 0;  
} 

常见的阻塞:wait、pause、sleep等函数;read或write某些文件时常见的阻塞:wait、pause、sleep等函数,它们本身就是阻塞的,
read或write阻塞与否,看你操作的对象是谁,

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


int main(void)  
{  
    // 读取鼠标  
    int fd = -1, ret = -1;  
    char buf[200];  
    fd_set myset;  
    struct timeval tm;  

    fd = open("/dev/input/mouse1", O_RDONLY);  
    if (fd < 0)  
    {  
        perror("open:");  
        return -1;  
    }  

    // 当前有2个fd,一共是fd一个是0  
    // 处理myset  
    FD_ZERO(&myset);  
    FD_SET(fd, &myset);  
    FD_SET(0, &myset);  

    tm.tv_sec = 10;  
    tm.tv_usec = 0;  

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

        if (FD_ISSET(fd, &myset))  
        {  
            // 这里处理鼠标  
            memset(buf, 0, sizeof(buf));  
            read(fd, buf, 50);  
            printf("鼠标读出的内容是:[%s].\n", buf);  
        }  
    }  

    return 0;  
}  

这个是poll的示例代码

#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;  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值