2
对于在应用层使用recv的时候,是网卡层将数据拷贝到系统的一个缓冲区,而我们仅仅是去读取这个缓冲区,读取之后,系统再为我们删除。 这样无疑就有如下操作:
引用
1:我们使用一个方式去轮训或者其他方法去查看是否有缓冲区可读
2:将内核缓冲区数据拷贝到用户态缓冲区
3:删除内核缓冲区数据
2:将内核缓冲区数据拷贝到用户态缓冲区
3:删除内核缓冲区数据
在 九剑的 Linux内核分析的文章中,了解到一些相关信息,这里我按照自己的理解来描述一下,并不一定准确。
在轮训的时候,如果数据匮乏,会出现大量的轮训查询,对于系统来说,无疑是一个巨大的资源浪费,当然我们可以联想到DMA技术,让网卡从主存中直接读取数据并操作主存,这样就将CPU解放出来
引用
1、首先,内核在主内存中为收发数据建立一个环形的缓冲队列(通常叫DMA环形缓冲区)。
2、内核将这个缓冲区通过DMA映射,把这个队列交给网卡;
3、网卡收到数据,就直接放进这个环形缓冲区了——也就是直接放进主内存了;然后,向系统产生一个中断;
4、内核收到这个中断,就取消DMA映射,这样,内核就直接从主内存中读取数据;
2、内核将这个缓冲区通过DMA映射,把这个队列交给网卡;
3、网卡收到数据,就直接放进这个环形缓冲区了——也就是直接放进主内存了;然后,向系统产生一个中断;
4、内核收到这个中断,就取消DMA映射,这样,内核就直接从主内存中读取数据;
另外发送数据的时候,同样是一个将数据拷贝到缓冲区的过程,而如果发送机制ACK确认,就将该缓冲区删除。另外有一些Socket选项,可以设置不适用内核缓冲区,直接使用用户态缓冲区,从理论来说,的确可以得到一定的优势,因为减少了很多操作过程。不过从安全角度考虑,我觉得这容易造成一个潜在的安全危险。
stupidcat
2009/08/31 00:45
发送的时候,如果设了某种socket选项,使得直接从用户缓冲区发送,那么,他一定有某种通知机制,比如Signal某个Event或者调用某个callback或者有某个标志位指示完成否,来使用户明确该传入缓冲区是否已被全部发送完,从而可以进行对该内存的安全覆盖或者释放。
stupidcat
2009/08/31 00:41
应该不会是轮询,效率太低了。
至少可以设个Event,然后recv的时候,用户线程挂起在该Event上,等内核收到数据,就SetEvent,使得用户线程唤醒,并将缓冲区数据copy到用户buffer内
至少可以设个Event,然后recv的时候,用户线程挂起在该Event上,等内核收到数据,就SetEvent,使得用户线程唤醒,并将缓冲区数据copy到用户buffer内
分页: 1/1
1
1
闷热的是天气,狂躁的是心态
几本书


2008/04/15
12:09
3160



