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