- 浏览: 1386523 次
- 性别:
- 来自: 火星
文章分类
最新评论
-
aidd:
内核处理time_wait状态详解 -
ahtest:
赞一下~~
一个简单的ruby Metaprogram的例子 -
itiProCareer:
简直胡说八道,误人子弟啊。。。。谁告诉你 Ruby 1.9 ...
ruby中的类变量与类实例变量 -
dear531:
还得补充一句,惊群了之后,数据打印显示,只有一个子线程继续接受 ...
linux已经不存在惊群现象 -
dear531:
我用select试验了,用的ubuntu12.10,内核3.5 ...
linux已经不存在惊群现象
这次我们来看后面的3个定时器;
首先是keep alive定时器。
这个定时器主要是由于一条连接可能长时间idle,此时就需要发送探测包,来探测对端是否存活,如果对端收到这个探测包,它会立即相应一个ack,而当接受到ack之后,我们就能确认对端是存活的。否则我们会认为这个连接除了问题。
这个定时器是当一个新的连接变为establish状态的时候被激活,如果在当定时器超时还没有数据到来,定时器回调函数就会被激活,从而发送探测包。
在linux中,keep alive定时器不仅实现了keep alive而且还实现了syn ack定时器。并且这个定时器必须主动被打开,我们在用户空间通过设置SO_KEEPALIVE 套接子选项来打开这个定时器。而在内核中是通过设置sock的sk_flag域来实现的。
上一篇的blog我们知道keepalive定时器的回掉函数是tcp_keepalive_timer,因此我们就来看这个函数的实现:
下面的keepalive_time_when 是用来计算我们keep alive定时器的时间间隔用的。
tp->keepalive_probes表示探测包的发送次数。
TCP_KEEPIDLE这个选项对应着tp->keepalive_time,表示idle状态的间隔时间,也就是说idle时间超过tp->keepalive_time才会发送探测包
TCP_KEEPINTVL这个选项对应着tp->keepalive_intvl ,而这个间隔表示定时器的间隔,也就是多长时间发送一次探测包。
接下来来看syn ack定时器。
这个定时器主要是用来管理连接队列。而且是用在服务端的。因为当三次握手最后一次,我们发送了syn-ack后,有可能需要重传syn-ack.而重传syn-ack这里一般有两个原因:
1 处于eastablished状态的连接,accept队列已满,使得应用程序不能接受新的连接。
2 当我们发送了syn-ack后,最后一个ack没有接受到,也就是3此握手没有完成。
第二个比较好理解,那么第一个呢。第一个之所以会这样,当accept队列满了之后,我们无法从半连接队列拷贝连接到accept队列,而我们拷贝半连接队列中的连接这个动作,是当ack到来时,我们才会激发这个动作,因此当accept队列满了,如果ack到来,我们会标记这个sock的acked域为1,此时由于不能拷贝连接,因此我们会等段时间重传这个syn-ack,从而等待ack的到来后拷贝这个半连接队列。
这个定时器什么时候会被启动呢,第一次一个连接加入到半连接队列的时候激活这个定时器。
而reqsk_queue_added的返回值为qlen,这个我们前面的blog已经介绍过了,这个值表示的是当前在半连接队列并且没有move到accept队列的连接个数。
而这个定时器什么时候被取消呢,和上面类似,也就是当最后一个在半连接队列中的连接被move到accept队列的时候。
接下来我们来看定时器的实现,它的实现函数就是tcp_synack_timer。这个函数直接会调用inet_csk_reqsk_queue_prune.
先来大概的介绍下这个函数的功能。
当半连接队列的连接个数超过最大个数的一半时,我们需要为接受年轻的连接(也就是没有重传过的连接)保留一半的空间。半连接队列里面要尽量保持young的连接,并remove掉一些长时间空闲或者没有accept的连接。这个清理工作的定时器就是syn ack定时器,而他的间隔是TCP_SYNQ_INTERVAL:
可以看到它的间隔是每秒5次。
最后我们要知道导致syn ack段的重传一般有下面两种情况:
1 3此握手完毕,可是accept 队列已满,此时inet_request_sock的acked域为1.
2 三次握手并没有完成,也就是最后的ack没有收到。此时inet_request_sock的acked域为0.
这个函数主要就是用来清理半连接队列中的一些老的连接,并重新发送syn-ack.
现在来看inet_csk_reqsk_queue_prune的实现:
下面这个图就是syn ack定时器的schedule。
最后我们来看 time_wait定时器。
我们知道当主动发起close的那端进入time_wait状态后,需要等待2个MSL那么长的时间,才能完全关闭这个连接。
而这个定时器什么时候被激活呢,当我们调用tcp_fin(以后我们会详细分析tcp连接的断开过程)或者tcp_close时,如果我们处于TCP_FIN_WAIT2状态,这时就会调用tcp_time_wait来启动这个定时器。
当我们进入TIME_WAIT状态,我们需要等待2个msl,才能完全关闭这个连接。linux实现这个是将所有的处于TW状态的sock放在了inet_ehash_bucket hash表的twchain中(详见前面的blog).
在linux中有两种途径执行tw定时器,其实也就是定时器的等待时间,一种就是2个msl,一种是基于RTO,计算出来的超时时间。选取哪一种依赖于下面的两个条件:
1 是否TW状态的sock recyle被允许.(也就是sysctl_tw_recycle被打开)
2 我么能够记住最近的段的时间戳。
如果上面两个环境都能满足,我们则调用tcp_v4_remember_stamp来检测是否对端的信息我们有保存。如果有保存,我们就进入recycle模式。
下面就来看tcp_time_wait的实现。
我们这里对TW定时器介绍的比较简略,后面当我们详细介绍tcp的关闭的4次握手时,会详细分析tw状态,倒是还会再联系这边进行分析。
首先是keep alive定时器。
这个定时器主要是由于一条连接可能长时间idle,此时就需要发送探测包,来探测对端是否存活,如果对端收到这个探测包,它会立即相应一个ack,而当接受到ack之后,我们就能确认对端是存活的。否则我们会认为这个连接除了问题。
这个定时器是当一个新的连接变为establish状态的时候被激活,如果在当定时器超时还没有数据到来,定时器回调函数就会被激活,从而发送探测包。
在linux中,keep alive定时器不仅实现了keep alive而且还实现了syn ack定时器。并且这个定时器必须主动被打开,我们在用户空间通过设置SO_KEEPALIVE 套接子选项来打开这个定时器。而在内核中是通过设置sock的sk_flag域来实现的。
上一篇的blog我们知道keepalive定时器的回掉函数是tcp_keepalive_timer,因此我们就来看这个函数的实现:
下面的keepalive_time_when 是用来计算我们keep alive定时器的时间间隔用的。
tp->keepalive_probes表示探测包的发送次数。
TCP_KEEPIDLE这个选项对应着tp->keepalive_time,表示idle状态的间隔时间,也就是说idle时间超过tp->keepalive_time才会发送探测包
TCP_KEEPINTVL这个选项对应着tp->keepalive_intvl ,而这个间隔表示定时器的间隔,也就是多长时间发送一次探测包。
static void tcp_keepalive_timer (unsigned long data) { struct sock *sk = (struct sock *) data; struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); __u32 elapsed; /* Only process if socket is not in use. */ bh_lock_sock(sk); ///如果有用户进程在使用这个sock,则重启定时器。 if (sock_owned_by_user(sk)) { /* Try again later. */ inet_csk_reset_keepalive_timer (sk, HZ/20); goto out; } ///我们上面说过了,keep alive定时器还可以处理ayn ack定时器。紧接着下面我们会分析这个定时器。 if (sk->sk_state == TCP_LISTEN) { tcp_synack_timer(sk); goto out; } ///如果状态为tcp_fin_wait,并且sock已经被关闭。则进入time_wait处理。 if (sk->sk_state == TCP_FIN_WAIT2 && sock_flag(sk, SOCK_DEAD)) { if (tp->linger2 >= 0) { const int tmo = tcp_fin_time(sk) - TCP_TIMEWAIT_LEN; if (tmo > 0) { ///time wait定时器还没有超时,则进入time wait定时器的处理. tcp_time_wait(sk, TCP_FIN_WAIT2, tmo); goto out; } } ///如果已经超时,则发送一个reset到对端。 tcp_send_active_reset(sk, GFP_ATOMIC); goto death; } ///检测keep alive有没有被打开。如果没有打开,则直接退出。 if (!sock_flag(sk, SOCK_KEEPOPEN) || sk->sk_state == TCP_CLOSE) goto out; ///取出那个空闲间隔时间。 elapsed = keepalive_time_when(tp); /* 1 tp->packets_out判断是否有任何已经传输可是还没有确认的数据包。 * 2 tcp_send_head用来判断是否有将要发送的包 * 如果上面有任何一个条件为真,就说明这个连接并不是处于idle状态,此时我们就重启定 *时器。 */ if (tp->packets_out || tcp_send_head(sk)) goto resched; ///接下来计算最后一次接收包到现在过去的时间。 elapsed = tcp_time_stamp - tp->rcv_tstamp; /*接下来比较idle时间有没有超过keep alive的设置的间隔时间,如果超过了,则说明我 *们需要 发送探测包了。如果没有,则我们需要重新调整keep alive的超时时间。 */ if (elapsed >= keepalive_time_when(tp)) { ///这个检测用来检测是否探测包已经超过了重发个数限制。 if ((!tp->keepalive_probes && icsk->icsk_probes_out >= sysctl_tcp_keepalive_probes) || (tp->keepalive_probes && icsk->icsk_probes_out >= tp->keepalive_probes)) { ///如果超过了限制,则我们认为连接已经断掉,此时我们发送一个reset给对端。 tcp_send_active_reset(sk, GFP_ATOMIC); tcp_write_err(sk); goto out; } /*调用tcp_write_wakeup发送一个探测包。如果哦发送成功我们增加icsk- * >icsk_probes_out,也就是发送次数。并且重新计算发送间隔。 */ if (tcp_write_wakeup(sk) <= 0) { icsk->icsk_probes_out++; ///这里计算探测时间间隔,并赋值给elapsed。 elapsed = keepalive_intvl_when(tp); } else { ///如果探测包丢失了,这表示有可能本地网络有问题,于是我们增加探测时间间隔, elapsed = TCP_RESOURCE_PROBE_INTERVAL; } } else { ///减小定时器的时间间隔。 elapsed = keepalive_time_when(tp) - elapsed; } TCP_CHECK_TIMER(sk); sk_mem_reclaim(sk); resched: ///重启定时器。超时时间为elapsed。 inet_csk_reset_keepalive_timer (sk, elapsed); goto out; death: tcp_done(sk); out: bh_unlock_sock(sk); sock_put(sk); }
接下来来看syn ack定时器。
这个定时器主要是用来管理连接队列。而且是用在服务端的。因为当三次握手最后一次,我们发送了syn-ack后,有可能需要重传syn-ack.而重传syn-ack这里一般有两个原因:
1 处于eastablished状态的连接,accept队列已满,使得应用程序不能接受新的连接。
2 当我们发送了syn-ack后,最后一个ack没有接受到,也就是3此握手没有完成。
第二个比较好理解,那么第一个呢。第一个之所以会这样,当accept队列满了之后,我们无法从半连接队列拷贝连接到accept队列,而我们拷贝半连接队列中的连接这个动作,是当ack到来时,我们才会激发这个动作,因此当accept队列满了,如果ack到来,我们会标记这个sock的acked域为1,此时由于不能拷贝连接,因此我们会等段时间重传这个syn-ack,从而等待ack的到来后拷贝这个半连接队列。
这个定时器什么时候会被启动呢,第一次一个连接加入到半连接队列的时候激活这个定时器。
static inline void inet_csk_reqsk_queue_added(struct sock *sk, const unsigned long timeout) { if (reqsk_queue_added(&inet_csk(sk)->icsk_accept_queue) == 0) inet_csk_reset_keepalive_timer(sk, timeout); }
而reqsk_queue_added的返回值为qlen,这个我们前面的blog已经介绍过了,这个值表示的是当前在半连接队列并且没有move到accept队列的连接个数。
而这个定时器什么时候被取消呢,和上面类似,也就是当最后一个在半连接队列中的连接被move到accept队列的时候。
static inline void inet_csk_reqsk_queue_removed(struct sock *sk, struct request_sock *req) { if (reqsk_queue_removed(&inet_csk(sk)->icsk_accept_queue, req) == 0) inet_csk_delete_keepalive_timer(sk); }
接下来我们来看定时器的实现,它的实现函数就是tcp_synack_timer。这个函数直接会调用inet_csk_reqsk_queue_prune.
先来大概的介绍下这个函数的功能。
当半连接队列的连接个数超过最大个数的一半时,我们需要为接受年轻的连接(也就是没有重传过的连接)保留一半的空间。半连接队列里面要尽量保持young的连接,并remove掉一些长时间空闲或者没有accept的连接。这个清理工作的定时器就是syn ack定时器,而他的间隔是TCP_SYNQ_INTERVAL:
#define TCP_SYNQ_INTERVAL (HZ/5)
可以看到它的间隔是每秒5次。
最后我们要知道导致syn ack段的重传一般有下面两种情况:
1 3此握手完毕,可是accept 队列已满,此时inet_request_sock的acked域为1.
2 三次握手并没有完成,也就是最后的ack没有收到。此时inet_request_sock的acked域为0.
这个函数主要就是用来清理半连接队列中的一些老的连接,并重新发送syn-ack.
现在来看inet_csk_reqsk_queue_prune的实现:
void inet_csk_reqsk_queue_prune(struct sock *parent, const unsigned long interval, const unsigned long timeout, const unsigned long max_rto) { ///这里省略了一些变量。 ............................................. if (lopt == NULL || lopt->qlen == 0) return; ///首先判断qlen是否已经超过了最大半连接数的一半,这里max_qlen_log是一个最大值的指数。如果超过了则开始计算半连接队列中的老的连接的最大重传次数(syn-ack重传).后面我们就会通过这个值来判断这个连接是否应该丢弃掉。 if (lopt->qlen>>(lopt->max_qlen_log-1)) { ///得到young连接的个数 int young = (lopt->qlen_young<<1); ///开始计算重试次数,初始值是最大的重传次数。 while (thresh > 2) { ///这里表示young连接现在在半连接队列中占据更多得个数。 if (lopt->qlen < young) break; ///这里可以看到当young连接的个数越多,thresh会越大,也就是重试次数会越大,而当young连接的个数越小,重试的次数就越小。这里很好得体现了我们需要保持young连接在半连接队列中的个数的领先。 thresh--; young <<= 1; } } ///如果用户设置了tcp_defer_accept选项,则设置最大重试次数为rskq_defer_accept if (queue->rskq_defer_accept) max_retries = queue->rskq_defer_accept; ///计算我们需要检测的半连接队列的个数(由于半连接队列是一个hash链表,并且它的数量可能非常巨大,我们如果每次都遍历全部,那样对协议栈的效率影响太大了,因此我们这里会计算一个预计值(这个值也就是表示遍历几个链表). budget = 2 * (lopt->nr_table_entries / (timeout / interval)); ///第一次clock_hand的值会为0,可是每次遍历完半连接队列,我们就会把最后的i,也就是最后一个hash链表的位置付给clock_hand,从而下一次遍历会从这里开始。 i = lopt->clock_hand; ///开始遍历半连接队列。 do { ///取出链表。 reqp=&lopt->syn_table[i]; ///遍历链表 while ((req = *reqp) != NULL) { ///首先判断这个request是否已经超时。这里要注意req->expires和syn-ack定时器的超时时间是不同的,它表示这个半连接的超时时间。每个半连接都有可能不同。 if (time_after_eq(now, req->expires)) { /*1 接下来判断重试次数是否小于thresh. * 2 acked域是否被设置(也就是表示accept队列已满),并且重试次数小于最大重试次数。 * 3 重发syn ack是否成功。 * 第1个和第二个判断是或的关系,而与第三个判断是与的关系。 */ if ((req->retrans < thresh || (inet_rsk(req)->acked && req->retrans < max_retries)) && !req->rsk_ops->rtx_syn_ack(parent, req)) { ///到达这里重新发送syn-ack成功。此时需要更新一些域。 unsigned long timeo; ///重试次数加1,如果第一次重传则将qlen_young见一。也就是说qlen_young保存的就是young连接的个数。 if (req->retrans++ == 0) lopt->qlen_young--; ///根据重传次数更新超时值(这里就是增大超时时间)。 timeo = min((timeout << req->retrans), max_rto); req->expires = now + timeo; reqp = &req->dl_next; continue; } ///否则从半连接队列中,丢掉这个连接。 inet_csk_reqsk_queue_unlink(parent, req, reqp); reqsk_queue_removed(queue, req); reqsk_free(req); continue; } reqp = &req->dl_next; } ///更新i,这里是为了循环处理,下面的图会很直观说明这个。 i = (i + 1) & (lopt->nr_table_entries - 1); } while (--budget > 0); ///更新clock_hand. lopt->clock_hand = i; ///重启定时器 if (lopt->qlen) inet_csk_reset_keepalive_timer(parent, interval); }
下面这个图就是syn ack定时器的schedule。
最后我们来看 time_wait定时器。
我们知道当主动发起close的那端进入time_wait状态后,需要等待2个MSL那么长的时间,才能完全关闭这个连接。
而这个定时器什么时候被激活呢,当我们调用tcp_fin(以后我们会详细分析tcp连接的断开过程)或者tcp_close时,如果我们处于TCP_FIN_WAIT2状态,这时就会调用tcp_time_wait来启动这个定时器。
当我们进入TIME_WAIT状态,我们需要等待2个msl,才能完全关闭这个连接。linux实现这个是将所有的处于TW状态的sock放在了inet_ehash_bucket hash表的twchain中(详见前面的blog).
在linux中有两种途径执行tw定时器,其实也就是定时器的等待时间,一种就是2个msl,一种是基于RTO,计算出来的超时时间。选取哪一种依赖于下面的两个条件:
1 是否TW状态的sock recyle被允许.(也就是sysctl_tw_recycle被打开)
2 我么能够记住最近的段的时间戳。
如果上面两个环境都能满足,我们则调用tcp_v4_remember_stamp来检测是否对端的信息我们有保存。如果有保存,我们就进入recycle模式。
下面就来看tcp_time_wait的实现。
void tcp_time_wait(struct sock *sk, int state, int timeo) { struct inet_timewait_sock *tw = NULL; const struct inet_connection_sock *icsk = inet_csk(sk); const struct tcp_sock *tp = tcp_sk(sk); int recycle_ok = 0; ///判断是否要进入recycle模式。 if (tcp_death_row.sysctl_tw_recycle && tp->rx_opt.ts_recent_stamp) recycle_ok = icsk->icsk_af_ops->remember_stamp(sk); ///检测tw状态的sock的桶的数目是否已经到达限制。如果没有则alloc一个tw。 if (tcp_death_row.tw_count < tcp_death_row.sysctl_max_tw_buckets) tw = inet_twsk_alloc(sk, state); if (tw != NULL) { ///复制相关的属性到tcptw和tw的域。 struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw); ///这里重新计算RTO. const int rto = (icsk->icsk_rto << 2) - (icsk->icsk_rto >> 1); tw->tw_rcv_wscale = tp->rx_opt.rcv_wscale; tcptw->tw_rcv_nxt = tp->rcv_nxt; tcptw->tw_snd_nxt = tp->snd_nxt; tcptw->tw_rcv_wnd = tcp_receive_window(tp); tcptw->tw_ts_recent = tp->rx_opt.ts_recent; tcptw->tw_ts_recent_stamp = tp->rx_opt.ts_recent_stamp; /* Linkage updates. */ ///这里将tw链接到tcp_hashinfo这个hash链表的tw chain中,而这个链表就是我们前面blog讲过的全局的包含所有sock的hash表struct inet_hashinfo; __inet_twsk_hashdance(tw, sk, &tcp_hashinfo); ///超时时间不能小于rto。 if (timeo < rto) timeo = rto; ///是否是recycle模式 if (recycle_ok) { ///如果是则tw等待时间为RTO tw->tw_timeout = rto; } else { ///否则就设置超时时间为TCP_TIMEWAIT_LEN tw->tw_timeout = TCP_TIMEWAIT_LEN; if (state == TCP_TIME_WAIT) timeo = TCP_TIMEWAIT_LEN; } ///开始schedule TW状态的sock。 inet_twsk_schedule(tw, &tcp_death_row, timeo, TCP_TIMEWAIT_LEN); inet_twsk_put(tw); } else { LIMIT_NETDEBUG(KERN_INFO "TCP: time wait bucket table overflow\n"); } tcp_update_metrics(sk); tcp_done(sk); }
我们这里对TW定时器介绍的比较简略,后面当我们详细介绍tcp的关闭的4次握手时,会详细分析tw状态,倒是还会再联系这边进行分析。
发表评论
-
Receive packet steering patch详解
2010-07-25 16:46 11956Receive packet steering简称rp ... -
内核中拥塞窗口初始值对http性能的影响分析
2010-07-11 00:20 9624这个是google的人提出的 ... -
linux 内核tcp拥塞处理(一)
2010-03-12 16:17 9491这次我们来分析tcp的拥塞控制,我们要知道协议栈都是很保守的, ... -
内核tcp协议栈SACK的处理
2010-01-24 21:13 12071上一篇处理ack的blog中我 ... -
内核tcp的ack的处理
2010-01-17 03:06 11069我们来看tcp输入对于ack,段的处理。 先是ack的处理, ... -
内核处理time_wait状态详解
2010-01-10 17:39 6705这次来详细看内核的time_wait状态的实现,在前面介绍定时 ... -
tcp协议栈处理各种事件的分析
2009-12-30 01:29 13560首先我们来看socket如何将一些状态的变化通知给对应的进程, ... -
linux内核sk_buff的结构分析
2009-12-25 00:42 47813我看的内核版本是2.6.32. 在内核中sk_buff表示一 ... -
tcp的输入段的处理
2009-12-18 00:56 8269tcp是全双工的协议,因此每一端都会有流控。一个tcp段有可能 ... -
内核协议栈tcp层的内存管理
2009-11-28 17:13 11920我们先来看tcp内存管理相关的几个内核参数,这些都能通过pro ... -
linux内核定时器的实现
2009-10-31 01:44 10121由于linux还不是一个实时的操作系统,因此如果需要更高精度, ... -
linux内核中tcp连接的断开处理
2009-10-25 21:47 10213我们这次主要来分析相关的两个断开函数close和shotdow ... -
linux内核tcp的定时器管理(一)
2009-10-04 23:29 9763在内核中tcp协议栈有6种 ... -
linux 内核tcp接收数据的实现
2009-09-26 20:24 14387相比于发送数据,接收数据更复杂一些。接收数据这里和3层的接口是 ... -
linux 内核tcp数据发送的实现
2009-09-10 01:41 19660在分析之前先来看下SO_RCVTIMEO和SO_SNDTIME ... -
tcp connection setup的实现(三)
2009-09-03 00:34 5128先来看下accept的实现. 其实accept的作用很简单, ... -
tcp connection setup的实现(二)
2009-09-01 00:46 8376首先来看下内核如何处理3次握手的半连接队列和accept队列( ... -
tcp connection setup的实现(一)
2009-08-23 04:10 5745bind的实现: 先来介绍几个地址结构. struct ... -
linux内核中socket的实现
2009-08-15 04:38 21001首先来看整个与socket相关的操作提供了一个统一的接口sys ... -
ip层和4层的接口实现分析
2009-08-08 03:50 6125首先来看一下基于3层的ipv4以及ipv6实现的一些4层的协议 ...
相关推荐
处理器 115 10.1 X86 115 10.2 ARM 115 10.3 Alpha AXP处理器 115 第11章 Linux内核源代码 117 11.1 怎样得到Linux内核源码 117 11.2 内核源码的编排 117 11.3 从何处看起 118 第12章 Linux...
Linux内核 前言 第1章 硬件基础与软件基础 6 1.1 硬件基础 6 1.1.1 CPU 7 1.1.2 存储器 8 1.1.3 总线 8 1.1.4 控制器和外设 8 1.1.5 地址空间 9 1.1.6 时钟 9 1.2 软件基础 9 1.2.1 计算机语言 9 1.2.2 什么是操作...
第二部分 Linux内核模块编程指南 致谢 前言 第1章 Hello, World 145 1.1 内核模块的Makefiles文件 146 1.2 多重文件内核模块 147 第2章 字符设备文件 149 第3章 /proc文件系统 158 第4章 把/proc用于输入 162 第5章 ...
-国嵌内核驱动进阶班-4-5(Linux内核定时器).avi -国嵌内核驱动进阶班-2-7(Uboot移植).avi -国嵌内核驱动进阶班-2-8(必修实验).avi -第5天(进程管理子系统) -国嵌内核驱动进阶班-5-1(LINUX进程控制).avi -...
第二部分 Linux内核模块编程指南 致谢 前言 第1章 Hello, World 145 1.1 内核模块的Makefiles文件 146 1.2 多重文件内核模块 147 第2章 字符设备文件 149 第3章 /proc文件系统 158 第4章 把/proc用于输入 162 第5章 ...
ZKQ090106 Linux内核裁剪与移植 嵌入式简介;Linux 基础知识;交叉编译;Linux 内核配置;Linux 内核移植;根文件系统制作;Boot Loader 制作。 第二学期 教学课时5个月 ZKQ090201 基于ARM7开发平台设计 ARM技术...
第二部分 Linux内核模块编程指南 致谢 前言 第1章 Hello, World 145 1.1 内核模块的Makefiles文件 146 1.2 多重文件内核模块 147 第2章 字符设备文件 149 第3章 /proc文件系统 158 第4章 把/proc用于输入 162 第5章 ...
第一部分 Linux内核 前言 第1章 硬件基础与软件基础 6 1.1 硬件基础 6 1.1.1 CPU 7 1.1.2 存储器 8 1.1.3 总线 8 1.1.4 控制器和外设 8 1.1.5 地址空间 9 1.1.6 时钟 9 1.2 软件基础 9 1.2.1 计算机语言 9 1.2.2 ...
-国嵌内核驱动进阶班-4-5(Linux内核定时器).avi -国嵌内核驱动进阶班-2-7(Uboot移植).avi -国嵌内核驱动进阶班-2-8(必修实验).avi -第5天(进程管理子系统) -国嵌内核驱动进阶班-5-1(LINUX进程控制).avi -...
第二部分 Linux内核模块编程指南 致谢 前言 第1章 Hello, World 145 1.1 内核模块的Makefiles文件 146 1.2 多重文件内核模块 147 第2章 字符设备文件 149 第3章 /proc文件系统 158 第4章 把/proc用于输入 162 第5章 ...
TCP源码分析 - 三次握手之 connect 过程 Linux网桥工作原理与实现 其他 定时器实现 多路复用I/O GDB原理之ptrace 容器相关 docker实现原理之 - namespace docker实现原理之 - CGroup介绍 docker实现原理之 - CGroup...
第二部分对高性能服务器编程的核心要素进行了全面深入的剖析,包含Linux网络编程API、高级I/O函数、Linux服务器程序规范、高性能服务器程序框架、I/O复用、信号、定时器、高性能I/O框架库Libevent、多进程编程、多...
第二部分 Linux内核模块编程指南 致谢 前言 第1章 Hello, World 145 1.1 内核模块的Makefiles文件 146 1.2 多重文件内核模块 147 第2章 字符设备文件 149 第3章 /proc文件系统 158 第4章 把/proc用于输入 162 第5章 ...
2、设计shell脚本程序,在屏幕上输出操作系统的信息,包括计算机名、Linux分发版本名称、Linux内核版本和当前的IP地址。 3、设计shell脚本程序,要求用户对/home目录下的文件进行备份,压缩为Linux系统中常用的tar....
当前的要求是希望工业控制设备能够支持TCP/IP以及其它Internet协议,从而能够通过用户熟悉的浏览器查看设备状态、设置设备参数,或者将设备采集到的数据通过网络传送到Windows或Unix/Linux服务器上的数据库中。...