I/O多路复用技术之select学习笔记

背景: I/O模型介绍

非阻塞I/O

检查–检查–检查。。。。-----------发起---------完成

阻塞I/O

发起------------------(阻塞)-----------------------完成

I/O复用

检查-----(阻塞)----------------就绪 发起-------完成
阻塞于select,而非I/O操作
与阻塞I/O相比,操作多出一步,效率较低,其优势在于一次可以等待多个fd

信号驱动I/O

通知发起-------------------------------------------------完成

异步I/O

发起-------------------------------------------------------通知

附:I/O多路复用流程图

使用过程中阻塞了两次

select函数

用途

指示内核等待多个事件中的任意一个发生,并在其中一个事件发生时唤醒进程
多个I/O使用一个线程或少量线程等待

函数原型

int select(int max_fd, fd_set *read_fd, fd_set *write_fd, fd_set *except_fd, struct timeval *timeout);
//return_val: 0 for time out  -1:err    other: the num of ready fd
//int max_fd:最大的fd加一,表示循环等待的最大fd
//下面fd_set:存储关心的文件集
//struct timeval: null for 永久等待      值为0 for 不等待    其它值 for 等待的时间
//struct timeval {
//	long tv_sec;//second
//	long tv_usec;//microsecond
//};

文件集操作

FD_ZERO(fd_set *set);//清空文件集
FD_SET(int fd, fd_set *set);//添加一个文件
FD_CLR(int fd, fd_set *set);//删除一个文件
FD_ISSET(int fd, fd_set *set);//判断某一个是否存在

注意事项

系统调用可以被信号打断,select也不例外,因此在使用select时,应检查errno是否出现EINTR错误。

例程

/*================================================================
*   Copyright (C) 2020 All rights reserved.
*   
*   Name      :select.c
*   Author    :wzj
*   Date      :2020.04.13
*   Decription:使用select等待/dev/tty(键盘)可读,
*               输入'q'退出当前进程
*               输入'\n'换行
*
================================================================*/


#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

int main()
{
	int fd;
	int max_fd;
	fd_set read_fd;
	struct timeval time_out;
	int ret;
	int read_num = 0;
	unsigned char read_char = 0;
	

	fd = open("/dev/tty", O_RDONLY | O_NONBLOCK, 0666);
	if(fd < 0) {
		printf("open file failed \n");
		return -1;
	}

	while(1) {
		FD_ZERO(&read_fd);
		FD_SET(fd, &read_fd);
		max_fd = fd + 1;
		ret = select(max_fd, &read_fd, NULL, NULL, NULL);	
		if(ret < 0) {
			if(errno == EINTR)
				continue;
				
			printf("select error\n");
			return - 1;
		}else if(ret == 0) {
			printf("time out \n");
			continue;
		}
	
		if(FD_ISSET(fd, &read_fd)) {
			read_num = read(fd, &read_char, 1);
			if(read_num <= 0) {
				printf("read file failed\n");
				return -3;
			}
			if(read_char == 'q') {
				printf("quit process\n");
				return 0;
			}	

			if(read_char == '\n') {
				printf("read new line\n");
				continue;
			}	
			printf("read %c\n", read_char);
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值