I/O Multiplexing

11 篇文章 0 订阅

The following is cited from APUE

/******************************************

One way to handle I/O multiplexing is to divide the process in two pieces(using fork), with each half handling one direction of data. If we use two processes, we can let each process do a blocking read. 

Second way is to use polling. We could use nonblocking I/O in a single process by setting both descriptors nonblocking and issuing a read on the first descriptor. If data is present, we read it and process it. If there is no data to read, the call returns immediately. We then do the same thing with the second descriptor. After this, we wait for some amount of time and then try to read from the first descriptor again. The problem is that it wastes CPU time. Most of the time, there won't be data to read, so we waste time performing the read system calls. Although is works on any system that supports nonblocking I/O, polling should be avoided on a multitasking system.

A better technique is to use I/O multiplexing. To do this, we build a list of the descriptors that doesn't return until one of descriptors is ready for I/O. On return from the function, we are told which descriptors are ready for I/O.

Three functions  - poll, pselect, select - allow us to perform I/O multiplexing.

The arguments we pass to select tell the kernel:

1, which descriptors we're interested in.

, what conditions we're interested in for each descriptor.

3. how long we want to wait.

On the return from select, the kernel tells us:

1. the total count of the number of descriptors that are ready.

2, which descriptors are ready for each of the three conditions.


int select(int maxfdp1, fd_set *restrict readfds, fd-set *restrict writefds, fd_set *restrict exceptfds, struct timeval *restrict tvptr)


On return from select, we can test whether a given bit int the set is still on using FD_ISSET:

if (FD_ISSET(fd, &rset)

{

...

}

If all three pointers are NULL, then we have a higher precision timer than provided by sleep.

The first argument to select, maxfdp1, stands for "maximum file descriptor plus 1".

It is important to realize that whether a descriptor is blocking or not doesn't affect whether select blocks. That is, if we have a nonblocking descriptor that we want tot read from and we call select with a timeout value of 5 seconds, select will block for up to 5 seconds. Similarly, if we specify an infinite timeout, select blocks until data is ready fro the descriptor or until a signal is caught.

/*************************************************************/

The following code is implemented by loop and I/O multiplexing.

The loop version:

str_len = recv(sockconn, recv_buffer, 1024, 0);

	int error;

	error = WSAGetLastError();

	if((error != 0 && error != WSAEWOULDBLOCK) || len == 0)
	{
		printf("\nLost connection!\n");
		for (i = 1; i <= MAX_FLOOR; i++)
		{
			if (floors_count[i] != 0)
			{
				if(TerminateProcess(pi[i].hProcess, 0))
				printf("进程的ID号:%d终止\n", pi[i].dwProcessId);
				else
				printf("进程关闭错误!\n");
			}
		}
		goto restart;
	}

The I/O multiplexing version:

while (fd_count)
	{
		FD_ZERO(&fdread);
		for (i = 1; i <= MAX_FLOOR; i++)
		{
			if (floors_count[i] != 0)
			{
				FD_SET(s[i], &fdread);
			}
		}
		//printf("I'm here!\n");
		ret = select(MAX_FLOOR + 1, &fdread, NULL, NULL, NULL);

		if (ret == 0)
		{
			continue;
		}

		for (i = 1; i <= MAX_FLOOR; i++)
		{
			if (FD_ISSET(s[i], &fdread))
			{
				// A read event happened on s[i]
				ret = recv(s[i], client_buffer[i], 1024, 0);
				if (ret == 0
						|| (ret == SOCKET_ERROR
								&& WSAGetLastError() == WSAECONNRESET))
				{
					// Client socket closed
					printf("Client socket %d closed.\n", 10000 + i);
					closesocket(s[i]);
					floors_count[i] = 0;
					fd_count--;

					if (TerminateProcess(pi[i].hProcess, 0))
						printf("进程的ID号:%d终止\n", pi[i].dwProcessId);

				}
				else
				{
					printf("%s\n", client_buffer[i]);
					send(sockconn, client_buffer[i], ret, 0);
				}
			}
		}
	}

we calculate the CPU usage by the two implementation, the loop version is 54% while the I/O multiplexing version is only 5%. So the I/O multiplexing is highly efficient.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值