|
在内核中我们发送数据一般使用dev_queue_xmit. 但是每次都需要通读等待返回, 通过线程的方式, 可以实现异步模式, 无需等待发送完成.可以大大加快发送速度.以下是示例代码:
static int xmit_thread_worker(void *arg);
///////////////////////////////////////////////////////////////////////////////
static struct task_struct *xmit_thread = NULL;
// 等待线程启动与完成
static struct completion start_done;
static struct completion end_done;
// 线程状态
static u32 thread_state = 0x0;
// 终止线程标记
static volatile u32 xmit_stop = 0x0;
// skb发送队列
struct sk_buff_head pkt_xmit;
///////////////////////////////////////////////////////////////////////////////
int xmit_thread_init(void)
{
int rc = 0x0;
// 初始化队列与completion
skb_queue_head_init( &pkt_xmit );
init_completion( &start_done );
init_completion( &end_done );
// 创建线程
xmit_thread = kthread_create( xmit_thread_worker, NULL, " ");
if ( IS_ERR( xmit_thread ) ) {
xmit_thread = NULL;
pr_err( "kthread_create occur error.\n" );
rc = -1;
}
else {
pr_emerg( "kthread_create success.\n" );
// 唤醒线程
wake_up_process( xmit_thread );
// 等待线程启动完成
wait_for_completion( &start_done );
pr_emerg( "xmit thread worker run success.\n" );
}
return rc;
}
// skb入队列发送
void xmit_enqueue( struct sk_buff *skb )
{
// skb 入队列
skb_queue_tail( &pkt_xmit, skb );
if ( NULL != xmit_thread ){
// 唤醒线程
wake_up_process( xmit_thread );
}
}
// 销毁线程
void xmit_thread_fini(void)
{
struct sk_buff *skb = NULL;
pr_emerg( "wait for xmit thread done\n" );
if ( NULL == xmit_thread ){
return ;
}
// 设置线程终止标记
xmit_stop = 0x1;
// 等待完成
wait_for_completion( &end_done );
// 释放队列中未发送skb
do {
skb = __skb_dequeue( &pkt_xmit );
if ( NULL != skb ) {
kfree_skb( skb );
}
}while( NULL != skb );
}
static int xmit_thread_worker(void *arg)
{
struct sk_buff *skb = NULL;
// 通知启动完成
complete( &start_done );
while( 1 ) {
thread_state = 0x0;
// 调度
schedule_timeout_interruptible(2);
//__set_current_state(TASK_RUNNING);
thread_state = 0x1;
// 是否终止?
if ( xmit_stop ) {
pr_emerg( "%s end.\n", __func__ );
break;
}
do {
// 取skb发送队列并发送
skb = skb_dequeue( &pkt_xmit );
if ( NULL != skb ) {
dev_queue_xmit( skb );
}
// 是否终止?
if ( xmit_stop ) {
pr_emerg( "%s end.\n", __func__ );
goto _out;
}
}while( NULL != skb );
};
_out:
// 通知线程终止
complete( &end_done );
return 0;
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/force_eagle/archive/2009/12/11/4983490.aspx
|Archiver|手机版|小黑屋|软路由 ( 渝ICP备15001194号-1|渝公网安备 50011602500124号 )
GMT+8, 2024-5-28 22:45 , Processed in 0.052829 second(s), 6 queries , Gzip On, Redis On.
Powered by Discuz! X3.5 Licensed
© 2001-2023 Discuz! Team.