目录
1.阻塞IO
CPU占用率低,等待资源时将任务挂起,不占用CPU资源,等到拿到资源后继续向下执行
read:
#include "head.h"
int main(void)
{
int fd = 0;
char tmpbuff[4096] = {0};
mkfifo("/tmp/myfifo", 0777);
fd = open("/tmp/myfifo", O_RDONLY);
if (-1 == fd)
{
perror("fail to open");
return -1;
}
while (1)
{
memset(tmpbuff, 0, sizeof(tmpbuff));
read(fd, tmpbuff, sizeof(tmpbuff));
printf("FIFO:%s\n", tmpbuff);
memset(tmpbuff, 0, sizeof(tmpbuff));
gets(tmpbuff);
printf("STDIN:%s\n", tmpbuff);
}
close(fd);
return 0;
}
write:
#include "head.h"
int main(void)
{
int fd = 0;
char tmpbuff[4096] = {0};
mkfifo("/tmp/myfifo", 0777);
fd = open("/tmp/myfifo", O_WRONLY);
if (-1 == fd)
{
perror("fail to open");
return -1;
}
while (1)
{
memset(tmpbuff, 0, sizeof(tmpbuff));
MY_GETS(tmpbuff);
write(fd, tmpbuff, strlen(tmpbuff));
}
close(fd);
return 0;
}
2.非阻塞IO
能够让任务不阻塞,效率低,因为没有数据时,CPU一直空转
程序步骤:
主要是获得俩个任务,一个是从终端输入,另一个是从管道输入
1.创建管道:mkfifo
2.打开管道: open
3.将文件描述符的属性中加入非阻塞属性
(1).获得文件描述符的属性:fcntl + F_GETFL;
(2).在现有的属性中加入非阻塞属性: |= O_NONBLOCK;
(3).将新的属性设置到文件描述符中: fcntl + F_SETFL;
4.循环得到俩个任务的值
(1).从管道中读取并打印:read
(2).从终端获得并打印:gets
5.关闭管道:close
详细如下
#include "head.h"
int main(void)
{
int fd = 0;
char tmpbuff[4096] = {0};
int flags;
ssize_t nsize = 0;
char *pret = NULL;
mkfifo("/tmp/myfifo", 0777);
fd = open("/tmp/myfifo", O_RDONLY);
if (-1 == fd)
{
perror("fail to open");
return -1;
}
/* 获得fd文件描述符的属性 */
flags = fcntl(fd, F_GETFL);
/* 在现有属性中加入非阻塞属性 */
flags |= O_NONBLOCK;
/* 将新属性设置回fd文件描述符 */
fcntl(fd, F_SETFL, flags);
flags = fcntl(0, F_GETFL);
flags |= O_NONBLOCK;
fcntl(0, F_SETFL, flags);
while (1)
{
memset(tmpbuff, 0, sizeof(tmpbuff));
nsize = read(fd, tmpbuff, sizeof(tmpbuff));
if (nsize > 0)
{
printf("FIFO:%s\n", tmpbuff);
}
memset(tmpbuff, 0, sizeof(tmpbuff));
pret = gets(tmpbuff);
if (NULL != pret)
{
printf("STDIN:%s\n", tmpbuff);
}
}
close(fd);
return 0;
}
write:
#include "head.h"
int main(void)
{
int fd = 0;
char tmpbuff[4096] = {0};
mkfifo("/tmp/myfifo", 0777);
fd = open("/tmp/myfifo", O_WRONLY);
if (-1 == fd)
{
perror("fail to open");
return -1;
}
while (1)
{
memset(tmpbuff, 0, sizeof(tmpbuff));
MY_GETS(tmpbuff);
write(fd, tmpbuff, strlen(tmpbuff));
}
close(fd);
return 0;
}
3.异步IO
将一个文件描述符设定为异步IO,当IO有事件发生时,内核会向用户层发送SIGIO信号提醒用户层处理事件
程序步骤:
主要是获得俩个任务,一个是从终端输入,另一个是从管道输入,再改变其属性
1.创建管道:mkfifo
2.打开管道: open
3.将文件描述符的属性中加入异步属性
(1).获得文件描述符的属性:fcntl + F_GETFL;
(2).在现有的属性中加入异步属性: |= O_ASYNC;
(3).将新的属性设置到文件描述符中: fcntl + F_SETFL;
(4) .当有文件描述符有任务时传给当前进程:fcntl + F_SETOWN 给 getpid();
4.当内核收到信号时,执行handler函数:signal + SIGIO
5.handler函数里写从管道中读取并打印:read
6.关闭管道:close
read:
#include "head.h"
int fd = 0;
void handler(int signo)
{
char tmpbuff[4096] = {0};
memset(tmpbuff, 0, sizeof(tmpbuff));
read(fd, tmpbuff, sizeof(tmpbuff));
printf("RECV:%s\n", tmpbuff);
return;
}
int main(void)
{
char tmpbuff[4096] = {0};
int flags;
signal(SIGIO, handler);
mkfifo("/tmp/myfifo", 0777);
fd = open("/tmp/myfifo", O_RDONLY);
if (-1 == fd)
{
perror("fail to open");
return -1;
}
flags = fcntl(fd, F_GETFL);
flags |= O_ASYNC;
//将fd设置为异步IO(文件描述符发生可以读的事件,会发送信号通知)
fcntl(fd, F_SETFL, flags);
//通知给当前进程
fcntl(fd, F_SETOWN, getpid());
while (1)
{
memset(tmpbuff, 0, sizeof(tmpbuff));
gets(tmpbuff);
printf("STDIN:%s\n", tmpbuff);
}
close(fd);
return 0;
}
write:
#include "head.h"
int main(void)
{
int fd = 0;
char tmpbuff[4096] = {0};
mkfifo("/tmp/myfifo", 0777);
fd = open("/tmp/myfifo", O_WRONLY);
if (-1 == fd)
{
perror("fail to open");
return -1;
}
while (1)
{
memset(tmpbuff, 0, sizeof(tmpbuff));
MY_GETS(tmpbuff);
write(fd, tmpbuff, strlen(tmpbuff));
}
close(fd);
return 0;
}
4.多路复用IO
1.select
监听文件描述符集合,将所有要监听的事件加入集合中,使用select监听所有事件,当集合中有事件发生,
select不再阻塞,同时select会将产生事件的文件描述符留在集合中,而把没有产生事件的文件描述符从
集合中踢出,所以留在集合中的文件描述即为产生事件的文件描述符,对其处理即可
1. 函数接口:
1.int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
功能:
监听文件描述符是否有事件发生
参数:
nfds:最大文件描述符的值 + 1
readfds:读文件描述符集合
writefds:写文件描述符集合
exceptfds:异常文件描述符集合
timeout:超时时间
返回值:
成功返回产生事件的文件描述符个数
失败返回-1
timeout时间到达仍然没有产生的事件返回0
void FD_CLR(int fd,