linux的Listen调用详解
2012-06-19 14:05
204 查看
listen系统可以使一台主机上的一个tcp
socket在某个端口号被动侦听,等待来自其它主机的tcp socket的连接请求,下面是listen系统调用的函数原型:
#include <sys/socket.h>
int listen(int
lsn_fd, int backlog);
backlog是侦听队列的长度,在内核函数中,首先对backlog作检查,如果大于128,则强制使其等于128。接下来要检查结构体struct
sock的成员sk_state,即当前socket的状态,如果不为TCP_LISTEN,则开始启动端口侦听。启动端口侦听首先要为结构体 struct inet_connection_sock(它是struc sock的扩展,表示一个面向连接的socket)的成员icsk_accept_queue分配内存,icsk_accept_queue的类型是 struct request_sock_queue,定义如下:
struct request_sock_queue
{
struct request_sock
*rskq_accept_head;
struct request_sock
*rskq_accept_tail;
rwlock_t
syn_wait_lock;
u8
rskq_defer_accept;
struct listen_sock
*listen_opt;
};
tcp socket在侦听的时候,那些来自其它主机的tcp
socket的连接请求一旦被接受(完成三次握手协议),便会建立一个request_sock,建立与请求socket之间的一个tcp连接。该 request_sock会被放在一个先进先出的队列中,等待accept系统调用的处理。但上面的结构体中好像并没有可以存放request_sock 的地方,下面是结构体struct listen_sock的定义:
struct listen_sock
{
u8
max_qlen_log;
int
qlen;
int
qlen_young;
int
clock_hand;
u32
hash_rnd;
u32
nr_table_entries;
struct
request_sock *syn_table[0];
};
新建立的request_sock就存放在syn_table中。这是一个哈希数组,总共有nr_table_entries项。实际上在分配内存时,分配的大小是TCP_SYNQ_HSIZE(512)项。成员nr_table_entries的值是512。成员max_qlen_log以2的对数的形式表示request_sock队列的最大值。哈希表有512项,但队列的最大值的取值是1024。即max_qlen_log的值为10。qlen是队列的当前长度。hash_rnd是一个随机数,计算哈希值用,结构体struct
request_sock_queue中的rskq_accept_head和rskq_accept_tail分别指向request_sock队列的队列头和队列尾。
为struct inet_connection_sock分配完内存后,继续处理,结构体struct
sock有两个成员sk_ack_backlog和sk_max_ack_backlog。sk_ack_backlog表示该侦听socket上,当前连向该socket,但是还没有完成三次握手协议的socket的数量,即还在连接过程中的socket的数量。初始值为 0,sk_max_ack_backlog为该数量的最大值,也就是listen系统调用的第二个参数,即侦听队列的长度,它的真正含义是:侦听 socket能处理的最大并发连接请求数,其最大取值为128。
到这里,把socket的状态改为TCP_LISTEN,进入侦听状态。然后独占端口,使socket进入mytcp_hashinfo哈希表集中的listening_hash表。侦听建立完成。
由于侦听socket始终在系统中进行侦听工作,所以在进程结束时,还必须显式结束侦听,进行相应的清理工作。
socket在某个端口号被动侦听,等待来自其它主机的tcp socket的连接请求,下面是listen系统调用的函数原型:
#include <sys/socket.h>
int listen(int
lsn_fd, int backlog);
backlog是侦听队列的长度,在内核函数中,首先对backlog作检查,如果大于128,则强制使其等于128。接下来要检查结构体struct
sock的成员sk_state,即当前socket的状态,如果不为TCP_LISTEN,则开始启动端口侦听。启动端口侦听首先要为结构体 struct inet_connection_sock(它是struc sock的扩展,表示一个面向连接的socket)的成员icsk_accept_queue分配内存,icsk_accept_queue的类型是 struct request_sock_queue,定义如下:
struct request_sock_queue
{
struct request_sock
*rskq_accept_head;
struct request_sock
*rskq_accept_tail;
rwlock_t
syn_wait_lock;
u8
rskq_defer_accept;
struct listen_sock
*listen_opt;
};
tcp socket在侦听的时候,那些来自其它主机的tcp
socket的连接请求一旦被接受(完成三次握手协议),便会建立一个request_sock,建立与请求socket之间的一个tcp连接。该 request_sock会被放在一个先进先出的队列中,等待accept系统调用的处理。但上面的结构体中好像并没有可以存放request_sock 的地方,下面是结构体struct listen_sock的定义:
struct listen_sock
{
u8
max_qlen_log;
int
qlen;
int
qlen_young;
int
clock_hand;
u32
hash_rnd;
u32
nr_table_entries;
struct
request_sock *syn_table[0];
};
新建立的request_sock就存放在syn_table中。这是一个哈希数组,总共有nr_table_entries项。实际上在分配内存时,分配的大小是TCP_SYNQ_HSIZE(512)项。成员nr_table_entries的值是512。成员max_qlen_log以2的对数的形式表示request_sock队列的最大值。哈希表有512项,但队列的最大值的取值是1024。即max_qlen_log的值为10。qlen是队列的当前长度。hash_rnd是一个随机数,计算哈希值用,结构体struct
request_sock_queue中的rskq_accept_head和rskq_accept_tail分别指向request_sock队列的队列头和队列尾。
为struct inet_connection_sock分配完内存后,继续处理,结构体struct
sock有两个成员sk_ack_backlog和sk_max_ack_backlog。sk_ack_backlog表示该侦听socket上,当前连向该socket,但是还没有完成三次握手协议的socket的数量,即还在连接过程中的socket的数量。初始值为 0,sk_max_ack_backlog为该数量的最大值,也就是listen系统调用的第二个参数,即侦听队列的长度,它的真正含义是:侦听 socket能处理的最大并发连接请求数,其最大取值为128。
到这里,把socket的状态改为TCP_LISTEN,进入侦听状态。然后独占端口,使socket进入mytcp_hashinfo哈希表集中的listening_hash表。侦听建立完成。
由于侦听socket始终在系统中进行侦听工作,所以在进程结束时,还必须显式结束侦听,进行相应的清理工作。
相关文章推荐
- linux的Listen调用详解
- linux的Listen调用详解
- linux的Listen调用详解
- linux的Listen调用详解
- Linux系统调用--fcntl函数详解
- command命令_Linux command 命令用法详解:调用并执行指定的命令
- uucico命令_Linux uucico 命令用法详解:Linux uucico命令UUCP文件传输服务程序。 uucico是用来处理uucp或uux送到队列的文件传输工具。uucico有两种工作模式:主动模式和附属模式。当在主动模式下时,uucico会调用远端主机;在附属模式下时,uucico则接受远端主机的调用。
- Linux系统调用--fcntl函数详解
- Linux系统调用--semctl函数详解
- Linux中TCP listen()的backlog参数详解
- Linux系统调用--fstat/stat/lstat函数详解
- Linux系统调用--mmap/munmap函数详解
- 《第一篇 linux 0.12 系统调用(int 0x80)详解》
- Linux系统调用--getrlimit()与setrlimit()函数详解
- Linux系统调用--getitimer/setitimer函数详解
- linux 启动流程详解之/init/main.c:init调用/etc/rc.d/rc.sysinit
- Linux makefile 和shell文件相互调用实例详解
- Linux系统调用-- recv/recvfrom/recvmsg函数详解(转)
- Linux系统调用--fcntl函数详解
- 详解linux系统调用原理