阻塞I/O 模式是最普遍使用的I/O 模式,大部分程序使用的都是阻塞模式的I/O 。
缺省情况下,套接字建立后所处于的模式就是阻塞I/O 模式。
前面学习的很多读写函数在调用过程中会发生阻塞。
读操作中的read、recv、recvfrom
写操作中的write、send
其他操作:accept、connect
以读阻塞为例:
当进程执行到读函数的时候
如果缓冲区里面有内容,程序读取完内容之后就继续向下执行,
如果缓冲区里面没有内容,进程就会进入休眠态,直到缓冲区里面有内容了
内核会唤醒该进程,然后进程过来读取缓冲区的内容,然后继续向下执行。
写操作也是会阻塞的,当写缓冲区满的时候就会阻塞
- #include
- #include
- #include
- #include
- #include
- #include
-
- int main(){
- int fd1 = open("./fifo1", O_RDONLY);
- int fd2 = open("./fifo2", O_RDONLY);
- int fd3 = open("./fifo3", O_RDONLY);
-
- char buff1[128] = {0};
- char buff2[128] = {0};
- char buff3[128] = {0};
-
- while(1){
- memset(buff1, 0, 128);
- read(fd1, buff1, 128);
- printf("buff1:[%s]\n", buff1);
-
- memset(buff2, 0, 128);
- read(fd2, buff2, 128);
- printf("buff2:[%s]\n", buff2);
-
- memset(buff3, 0, 128);
- read(fd3, buff3, 128);
- printf("buff3:[%s]\n", buff3);
- }
-
- close(fd1);
- close(fd2);
- close(fd3);
-
- return 0;
- }
- #include
- #include
- #include
- #include
- #include
- #include
-
- int main(){
- int fd = open("./fifo1", O_WRONLY);
-
- char buff[128] = {0};
-
- while(1){
- memset(buff, 0, 128);
- fgets(buff, 128, stdin);
- buff[strlen(buff)-1] = '\0';
- write(fd, buff, 128);
- }
-
- close(fd);
-
- return 0;
- }
以读阻塞为例:
当进程执行到读函数的时候
如果缓冲区里面有内容,程序读取完内容之后就继续向下执行,
如果缓冲区里面没有内容,进程就不进入休眠态,而是立即返回一个错误
这种情况下就需要我们轮询去执行操作,这种操作是十分占用CPU的
一般不推荐使用
一般阻塞函数都有一个能设置非阻塞方式的选项
如 recv 和 recvfrom 的 MSG_DONTWAIT
waitpid 的 WNOHONG
O_NONBLOCK
对于read这种函数,本身是没有非阻塞选项的,这是可以使用 fcntl 函数来设置非阻塞
- int flag = fcntl(fd, F_GETFL);//获取原来的状态
- flag |= O_NONBLOCK;//添加非阻塞属性
- fcntl(fd, F_SETFL, flag);//再设置回去
- #include
- #include
- #include
- #include
- #include
- #include
-
- int main(){
- int fd1 = open("./fifo1", O_RDONLY);
- int fd2 = open("./fifo2", O_RDONLY);
- int fd3 = open("./fifo3", O_RDONLY);
-
- char buff1[128] = {0};
- char buff2[128] = {0};
- char buff3[128] = {0};
-
- //将文件描述符都设置成非阻塞
- int flag = fcntl(fd1, F_GETFL);
- flag |= O_NONBLOCK;
- fcntl(fd1, F_SETFL, flag);
-
- flag = fcntl(fd2, F_GETFL);
- flag |= O_NONBLOCK;
- fcntl(fd2, F_SETFL, flag);
-
- flag = fcntl(fd3, F_GETFL);
- flag |= O_NONBLOCK;
- fcntl(fd3, F_SETFL, flag);
-
- while(1){
- memset(buff1, 0, 128);
- read(fd1, buff1, 128);
- printf("buff1:[%s]\n", buff1);
-
- memset(buff2, 0, 128);
- read(fd2, buff2, 128);
- printf("buff2:[%s]\n", buff2);
-
- memset(buff3, 0, 128);
- read(fd3, buff3, 128);
- printf("buff3:[%s]\n", buff3);
-
- //sleep(1);//此处的sleep(1) 是为了防止刷屏
- //能看到现象的,正常应该是没有的
- //如果没有这个sleep 使用 top可以看到
- //该进程 基本已经把CPU占满了
- }
-
- close(fd1);
- close(fd2);
- close(fd3);
-
- return 0;
- }