您的位置:首页 > 其它

select多路复用

2016-01-24 23:09 507 查看
1.在socket的使用中我们经常用多路复用的方式来避免使用while的循环查询监听,至于如何使用详细的请看man 2 select

int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);


nfds:被监听的描述符

readfs:可读描述符集

writedfs:可写描述符集

timeout:堵塞时间

例子:

#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
#include <time.h>

void display_time(const char *str)
{
int seconds;
seconds = time((time_t*)NULL);
printf("%s,%d\n",str,seconds);
}

int main(void)
{
fd_set readfds;
struct timeval timeout;
int ret;
FD_ZERO(&readfds);
FD_SET(0,&readfds);

timeout.tv_sec = 10;
timeout.tv_usec = 0;
while(1)
{
display_time("before select");
ret = select(1,&readfds,NULL,NULL,&timeout);

switch(ret){
case 0:
printf("NO DATA IN TEN SECONDS.\n");exit(0);break;
case -1:
perror("SELECT");
exit(1);break;
default:
getchar();
printf("Data is avilable now.\n");
}
}
return 0;

}

重要的是时间的设置,这里我们使用10秒堵塞的时间,在十秒内如果描述符readfds有可读的加入就立即返回,否则一直等待知道10秒后返回0

不过有趣的是我在反汇编看到

.file	"select.c"
.section	.rodata.str1.1,"aMS",@progbits,1
.LC0:
.string	"%s,%d\n"
.text
.globl display_time
.type	display_time, @function
display_time:
.LFB33:
.cfi_startproc
pushq	%rbx
.cfi_def_cfa_offset 16
movq	%rdi, %rbx
.cfi_offset 3, -16
movl	$0, %edi
call	time
movl	%eax, %ecx
movq	%rbx, %rdx
movl	$.LC0, %esi
movl	$1, %edi
movl	$0, %eax
call	__printf_chk
popq	%rbx
ret
.cfi_endproc
.LFE33:
.size	display_time, .-display_time
.section	.rodata.str1.1
.LC1:
.string	"before select"
.LC2:
.string	"NO DATA IN TEN SECONDS.\n"
.LC3:
.string	"SELECT"
.LC4:
.string	"Data is avilable now.\n"
.text
.globl main
.type	main, @function
main:
.LFB34:
.cfi_startproc
pushq	%rbp
.cfi_def_cfa_offset 16
pushq	%rbx
.cfi_def_cfa_offset 24
subq	$152, %rsp
.cfi_def_cfa_offset 176
movq	%rsp, %rdi
movl	$16, %ecx
movl	$0, %eax
#APP
# 18 "select.c" 1
cld; rep; stosq
# 0 "" 2
#NO_APP
orq	$1, (%rsp)
movq	$10, 128(%rsp)
movq	$0, 136(%rsp)
leaq	128(%rsp), %rbx
.cfi_offset 3, -24
.cfi_offset 6, -16
.L7:
movl	$.LC1, %edi
call	display_time
movq	%rbx, %r8
movl	$0, %ecx
movl	$0, %edx
movq	%rsp, %rsi
movl	$1, %edi
call	select
cmpl	$-1, %eax
je	.L5
testl	%eax, %eax//这里不是一直为正确的状态么?(意味着.L9的跳转是必然)
jne	.L9
movl	$.LC2, %esi
movl	$1, %edi
call	__printf_chk
movl	$0, %edi
call	exit
.L5:
movl	$.LC3, %edi
call	perror
movl	$1, %edi
call	exit
.L9:
movq	stdin(%rip), %rdi
call	_IO_getc
movl	$.LC4, %esi
movl	$1, %edi
movl	$0, %eax
call	__printf_chk
jmp	.L7
.cfi_endproc
.LFE34:
.size	main, .-main
.ident	"GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5.1) 4.4.5"
.section	.note.GNU-stack,"",@progbits
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: