一 阻塞IO
1.1概念:
阻塞I/O 模式是最普遍使用的I/O 模式,大部分程序使用的都是阻塞模式的I/O 。
缺省情况下,套接字建立后所处于的模式就是阻塞I/O 模式。
前面学习的很多读写函数在调用过程中会发生阻塞。
读操作中的read、recv、recvfrom
写操作中的write、send
其他操作:accept、connect
以读阻塞为例:
当进程执行到读函数的时候
如果缓冲区里面有内容,程序读取完内容之后就继续向下执行,
如果缓冲区里面没有内容,进程就会进入休眠态,直到缓冲区里面有内容了
内核会唤醒该进程,然后进程过来读取缓冲区的内容,然后继续向下执行。
写操作也是会阻塞的,当写缓冲区满的时候就会阻塞
1.2代码实现:
1.2.1读端
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
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;
}
1.2.2写端(三个写端都是一样的,只不过名字不一样)
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
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;
}
二非阻塞IO
2.1概念
以读阻塞为例:
当进程执行到读函数的时候
如果缓冲区里面有内容,程序读取完内容之后就继续向下执行,
如果缓冲区里面没有内容,进程就不进入休眠态,而是立即返回一个错误
这种情况下就需要我们轮询去执行操作,这种操作是十分占用CPU的
一般不推荐使用
一般阻塞函数都有一个能设置非阻塞方式的选项
如 recv 和 recvfrom 的 MSG_DONTWAIT
waitpid 的 WNOHONG
O_NONBLOCK
对于read这种函数,本身是没有非阻塞选项的,这是可以使用 fcntl 函数来设置非阻塞
2.2fcntl函数的说明:
int flag = fcntl(fd, F_GETFL);//获取原来的状态
flag |= O_NONBLOCK;//添加非阻塞属性
fcntl(fd, F_SETFL, flag);//再设置回去
2.3代码说明:
2.3.1读端:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
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;
}
2.3.2写端和上面一样
版权声明:本文为a2998658795原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。