接上篇
阻塞IO、非阻塞IO、IO多路复用和信号驱动IO简介-CSDN博客文章浏览阅读90次。阻塞IO、非阻塞IO、IO多路复用和信号驱动IO简介https://blog.csdn.net/CSDN_DU666666/article/details/139598410?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22139598410%22%2C%22source%22%3A%22CSDN_DU666666%22%7D
以读操作为例,当进程执行读操作的时候,如果缓冲区内有内容,则读取内容继续执行。
如果缓冲区没有内容,则立即返回一个错误,而非让进程进入休眠状态。
但是,这种操作需要配合一个循环不停的测试是否有数据可读,这种操作十分浪费CPU,一般不推荐。
有些函数本身自带非阻塞标志位
eg: waitpid的WHOHANG
recv和recvfrom的MSG_DONTWAIT O_NONBLOCK
但对于大部分的函数并没有非阻塞标志位,可以使用fcntl函数设置非阻塞标志位
功能:
控制文件描述符状态
头文件:
#include <unistd.h>
#include <fcntl.h>
函数原型:
int fcntl(int fd, int cmd, ... /* arg */ );
参数:
fd 文件描述符
cmd 要控制的方式
F_GETFL 获取文-件描述符的状态 arg被忽略
F_SETFL 设置文件描述符的状态 arg为int类型
文件描述符的状态 O_NONBLOCK 表示非阻塞
... 可变参 有没有 以及什么类型 都取决于 cmd
返回值:
cmd是 F_GETFL 成功 返回文件状态标志位 失败返回-1 重置错误码
cmd是 F_SETFL 成功 返回 0 失败返回-1 重置错误码
使用fcntl设置非阻塞:
int flag = fcntl(fd,F_GETFL);
flag|=O_NONBLOCK;
fcntl(fd,F_SETFL,flag);
首先创建三个管道文件
指令:mkfifo fifo1
mkfifo fifo2
mkfifo fifo3
service.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char *argv[])
{
int fd1, fd2, fd3;
if (-1 == (fd1 = open("fifo1", O_RDONLY)))
{
PRINT_ERR("open fifo1 error");
}
if (-1 == (fd2 = open("fifo2", O_RDONLY)))
{
PRINT_ERR("open fifo2 error");
}
if (-1 == (fd3 = open("fifo3", O_RDONLY)))
{
PRINT_ERR("open fifo3 error");
}
char buff[128] = {0};
int flag = 0;
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)
{
sleep(1);
memset(buff, 0, sizeof(buff));
read(fd1, buff, sizeof(buff));
printf("buff1=%s\n", buff);
memset(buff, 0, sizeof(buff));
read(fd2, buff, sizeof(buff));
printf("buff2=%s\n", buff);
memset(buff, 0, sizeof(buff));
read(fd3, buff, sizeof(buff));
printf("buff3=%s\n", buff);
sleep(1); // 此处sleep(1)是为了看现象 防止刷屏
}
close(fd1);
close(fd2);
close(fd3);
return 0;
}
client.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc, const char *argv[]){
int fd = open("fifo1", O_WRONLY);//fifo2 fiof3
char buff[128] = {0};
while(1){
memset(buff, 0, 128);
printf("请输入:");
fgets(buff, 128, stdin);
buff[strlen(buff)-1] = '\0';
write(fd, buff, 128);
}
close(fd);
return 0;
}