注册 登录
自由的生活_软路由 返回首页

11的个人空间 https://bbs.routerclub.com/?499 [收藏] [复制] [分享] [RSS]

日志

在内核中使用线程与skb队列发送数据

已有 539 次阅读2012-3-31 22:54 | 数据

在内核中我们发送数据一般使用dev_queue_xmit. 但是每次都需要通读等待返回, 通过线程的方式, 可以实现异步模式, 无需等待发送完成.可以大大加快发送速度.以下是示例代码:

  1. static int xmit_thread_worker(void *arg);  
  2.   
  3. ///////////////////////////////////////////////////////////////////////////////  
  4. static struct task_struct   *xmit_thread = NULL;  
  5. // 等待线程启动与完成  
  6. static struct completion    start_done;  
  7. static struct completion    end_done;  
  8. // 线程状态  
  9. static u32                  thread_state = 0x0;  
  10. // 终止线程标记  
  11. static volatile u32         xmit_stop    = 0x0;  
  12. // skb发送队列  
  13. struct sk_buff_head         pkt_xmit;  
  14. ///////////////////////////////////////////////////////////////////////////////  
  15.   
  16. int xmit_thread_init(void)  
  17. {  
  18.     int rc = 0x0;  
  19.     // 初始化队列与completion  
  20.     skb_queue_head_init( &pkt_xmit );  
  21.     init_completion( &start_done );  
  22.     init_completion( &end_done );  
  23.     // 创建线程  
  24.     xmit_thread = kthread_create( xmit_thread_worker, NULL, " ");  
  25.     if ( IS_ERR( xmit_thread ) ) {  
  26.         xmit_thread = NULL;  
  27.         pr_err( "kthread_create occur error./n" );  
  28.         rc = -1;  
  29.     }  
  30.     else {  
  31.         pr_emerg( "kthread_create success./n" );  
  32.                 // 唤醒线程  
  33.         wake_up_process( xmit_thread );  
  34.                 // 等待线程启动完成  
  35.         wait_for_completion( &start_done );  
  36.         pr_emerg( "xmit thread worker run success./n" );  
  37.     }  
  38.     return rc;  
  39. }  
  40. // skb入队列发送  
  41. void xmit_enqueue( struct sk_buff *skb )  
  42. {  
  43.         // skb 入队列  
  44.     skb_queue_tail( &pkt_xmit, skb );  
  45.     if ( NULL != xmit_thread ){  
  46.                 // 唤醒线程  
  47.         wake_up_process( xmit_thread );  
  48.     }  
  49. }  
  50. // 销毁线程  
  51. void xmit_thread_fini(void)  
  52. {  
  53.     struct sk_buff *skb = NULL;  
  54.       
  55.     pr_emerg( "wait for xmit thread done/n" );  
  56.     if ( NULL == xmit_thread ){  
  57.         return ;  
  58.     }  
  59.     // 设置线程终止标记  
  60.     xmit_stop = 0x1;  
  61.         // 等待完成  
  62.     wait_for_completion( &end_done );  
  63.     // 释放队列中未发送skb  
  64.     do {  
  65.         skb = __skb_dequeue( &pkt_xmit );  
  66.         if ( NULL != skb ) {  
  67.             kfree_skb( skb );  
  68.         }  
  69.     }while( NULL != skb );    
  70. }  
  71.   
  72. static int xmit_thread_worker(void *arg)  
  73. {  
  74.     struct sk_buff *skb = NULL;  
  75.         // 通知启动完成  
  76.     complete( &start_done );  
  77.     while( 1 ) {  
  78.         thread_state = 0x0;  
  79.                 // 调度  
  80.         schedule_timeout_interruptible(2);  
  81.   
  82.         //__set_current_state(TASK_RUNNING);  
  83.           
  84.         thread_state = 0x1;  
  85.         // 是否终止?  
  86.         if ( xmit_stop ) {  
  87.             pr_emerg( "%s end./n", __func__ );  
  88.             break;  
  89.         }  
  90.         do {  
  91.                         // 取skb发送队列并发送  
  92.             skb = skb_dequeue( &pkt_xmit );  
  93.             if ( NULL != skb ) {  
  94.                 dev_queue_xmit( skb );  
  95.             }  
  96.             // 是否终止?  
  97.             if ( xmit_stop ) {  
  98.                 pr_emerg( "%s end./n", __func__ );  
  99.                 goto _out;  
  100.             }  
  101.         }while( NULL != skb );  
  102.     };  
  103. _out:  
  104.         // 通知线程终止  
  105.     complete( &end_done );  
  106.     return 0;  
  107. }  

分享到: 

路过

雷人

握手

鲜花

鸡蛋

评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

QQ|Archiver|手机版|小黑屋|软路由 ( 渝ICP备15001194号-1|渝公网安备 50011602500124号 )

GMT+8, 2024-6-2 07:24 , Processed in 0.176678 second(s), 5 queries , Gzip On, Redis On.

Powered by Discuz! X3.5 Licensed

© 2001-2023 Discuz! Team.

返回顶部