免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 15383 | 回复: 11
打印 上一主题 下一主题

del_timer与del_timer_sync的区别 测试结果与LKD3描述不同 [复制链接]

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-11-26 09:08 |只看该作者 |倒序浏览
本帖最后由 瀚海书香 于 2010-11-26 10:18 编辑

根据LKD3上的说法,在允许睡眠的情况下,应该使用del_timer_sync函数来取消掉timer,因为del_timer在多核的系统上可能会导致core 1去del_timer时,core 0上正在运行timer,从而导致bug。但是我实际测试了一下在双核的情况下,并没有出现问题?
下面是我的测试代码。
timer的内核代码:
  1. #include <linux/module.h>
  2. #include <linux/version.h>
  3. #include <asm/param.h>
  4. #include <linux/timer.h>
  5. MODULE_LICENSE("GPL");
  6. MODULE_DESCRIPTION("timer");

  7. struct timer_list timer;
  8. static void fun(unsigned long arg)
  9. {
  10.         char *v=arg;
  11.         unsigned long now = jiffies;
  12.         unsigned int i;
  13.         printk("%s\n",v);
  14.         while(jiffies < (now+10*HZ)){
  15.                 cpu_relax();
  16.         }
  17.         /*for(i=0;i<20000;i++)
  18.                 printk(KERN_INFO "%s\n",v);*/
  19.         printk("%s\n",v);
  20.         mod_timer(&timer,jiffies+HZ*5);
  21.         printk(KERN_ALERT "%u\n",HZ);
  22. }
  23. static int __init init(void)
  24. {
  25.         char *var="ltw\n";
  26.         init_timer(&timer);
  27.         timer.function=&fun;
  28.         timer.expires=jiffies+HZ;
  29.         timer.data=var;
  30.         add_timer(&timer);
  31.         return 0;
  32. }
  33. static void __exit fini(void)
  34. {
  35.         del_timer(&timer);
  36.         return;
  37. }
  38. module_init(init);
  39. module_exit(fini);
复制代码
指定cpu去卸载模块的代码  delmodule:
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <sys/types.h>
  4. #include <sys/sysinfo.h>
  5. #include <unistd.h>
  6. #define __USE_GNU
  7. #include <sched.h>
  8. #include <ctype.h>
  9. #include <string.h>
  10. int main(int argc, char* argv[])
  11. {
  12.         int num = sysconf(_SC_NPROCESSORS_CONF);
  13.         int created_thread = 0;
  14.         int myid;
  15.         int i;
  16.         int j = 0;
  17.         cpu_set_t mask;
  18.         cpu_set_t get;
  19.         if (argc != 2){
  20.                 printf("usage : ./cpu num\n");
  21.                 exit(1);
  22.         }
  23.         myid = atoi(argv[1]);
  24.         printf("system has %i processor(s). \n", num);
  25.         CPU_ZERO(&mask);
  26.     CPU_SET(myid, &mask);
  27.     if (sched_setaffinity(0, sizeof(mask), &mask) == -1)
  28.     {
  29.         printf("warning: could not set CPU affinity, continuing...\n");
  30.     }
  31.     CPU_ZERO(&get);
  32.    if (sched_getaffinity(0, sizeof(get), &get) == -1)
  33.    for (i = 0; i < num; i++)
  34.    {
  35.         if (CPU_ISSET(i, &get))
  36.             printf("this process %d is running processor : %d\n",getpid(), i);
  37.     }
  38.     sleep(3);
  39.     system("rmmod timer.ko");
  40.     return 0;
  41. }
复制代码
首先在一个终端运行./delmodule 1指定cpu 1在3秒后执行rmmod. 同时在另一个终端运行insmod timer.ko. 运行结果:内核没有崩溃,在timer执行完后才delmodule才成功返回(大约十秒,而不是3秒)。

首先在一个终端运行./delmodule 0指定cpu 0在3秒后执行rmmod. 同时在另一个终端运行insmod timer.ko. 运行结果:内核没有崩溃,在timer执行完后才delmodule才成功返回(大约十秒,而不是3秒)。

是代码写的有问题还是测试方法有问题?

论坛徽章:
0
2 [报告]
发表于 2010-11-26 14:03 |只看该作者
首先你定时器的时长为5秒,你能确保在卸载的时候该定时器正在执行吗?

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
3 [报告]
发表于 2010-11-26 14:10 |只看该作者
回复 2# suiming2005
定时器的时长是5秒,但是定时器第一次被调用却是模块加载后1秒。
  1.     init_timer(&timer);

  2.         timer.function=&fun;

  3.         timer.expires=jiffies+HZ;

  4.         timer.data=var;

  5.         add_timer(&timer);
复制代码
也就是说,首先执行delmodule,然后马上在另一个终端insmod。大约3秒钟后,delmodule开始rmmod,而这时timer应该执行了大约2秒,还没有完全执行完。

论坛徽章:
0
4 [报告]
发表于 2010-12-01 11:23 |只看该作者
本帖最后由 kouu 于 2010-12-01 11:35 编辑

我觉得LZ的测试代码不造成内核崩溃是正常的。

del_timer要做的事情是把timer从待处理链表里面detach,并不是要销毁这个timer对象; 这件事情跟timer.function回调函数正在被执行本身毫无瓜葛,怎么可能会引起崩溃呢?

当然,这个地方确实是需要注意的,del_timer和timer.function是可以同时发生的。(del_timer和__run_timers都会给tvec_base上锁,但是__run_timers在调用timer.function的时候会先把锁释放掉。)

考虑下面一种情况:调用del_timer以后,我们可能会kfree(timer)把对象销毁掉、把与这个timer相关的对象也销毁掉(这些对象可能会被timer.function访问)。
而在timer.function里面,我们又可能会通过arg参数把timer传进去,然后调用mod_timer之类的;又或者会在timer.function里面访问那些与timer相关的对象(这些对象我们在del_timer之后已经销毁了……)。如果是这样,就应该使用del_timer_sync,必须等到timer.function完成了,才能做那些销毁工作。如果del_timer以后我们不对timer.function里面需要访问的任何数据产生影响,那么也就不需要del_timer_sync了。
话说回来,如果del_timer在SMP环境下随便怎么用有问题,那么这么久了,有问题怎么还不修,还留着这个函数干什么……

至于delmodule成功返回是在10秒之后(而不是3秒)的问题,我觉得是这样的:delmodule会把module的代码unmap掉,其中就包括timer.function。但是timer.function正在被调用呢,不可能把正在执行的代码卸掉吧~ 所以得等它调用完,也就等到10秒之后了。(这部分代码没看过,纯猜想。)

个人理解,欢迎讨论。

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
5 [报告]
发表于 2010-12-01 13:02 |只看该作者
而在timer.function里面,我们又可能会通过arg参数把timer传进去,然后调用mod_timer之类的;又或者会在timer.function里面访问那些与timer相关的对象(这些对象我们在del_timer之后已经销毁了……)。如果是这样,就应该使用del_timer_sync,必须等到timer.function完成了,才能做那些销毁工作。

但是我的代码里的确是用来timer.data来传递了参数var的啊。比如timer的function函数就是通过arg来传递的啊。

  1. static void fun(unsigned long arg)
  2. {
  3.         char *v=arg;
  4.         。。。。。。
  5. }
复制代码
那按照大虾的说法,使用del_timer会出问题的啊?

论坛徽章:
0
6 [报告]
发表于 2010-12-01 14:01 |只看该作者
而在timer.function里面,我们又可能会通过arg参数把timer传进去,然后调用mod_timer之类的;又或者会在timer.function里面访问那些与timer相关的对象(这些对象我们在del_timer之后已经销毁了……)

但是我的代码里的确是用来timer.data来传递了参数var的啊。比如timer的function函数就是通过arg来传递的啊 ...
瀚海书香 发表于 2010-12-01 13:02


按我的理解,关键不在于我们传了什么东西进去,而在于我们在timer.function里面引用的内存或者其他资源,可能已经被释放了。
为什么会被释放呢?因为我们错误的以为del_timer之后,这些“东西”就可以被释放。但是实际上,del_timer之后,timer.function可能还在运行,释放这些“东西”是可能会出问题的。
所以在释放这些“东西”之前,除了调用del_timer把timer从待处理队列里面detach之外,如果timer.function正在执行,还需要等它执行完。这就是del_timer_sync干的事情。

论坛徽章:
0
7 [报告]
发表于 2010-12-01 14:34 |只看该作者
6.5.1.1. Dynamic timers and race conditions

Being asynchronously activated, dynamic timers are prone to race conditions. For instance, consider a dynamic timer whose function acts on a discardable resource (e.g., a kernel module or a file data structure). Releasing the resource without stopping the timer may lead to data corruption if the timer function got activated when the resource no longer exists. Thus, a rule of thumb is to stop the timer before releasing the resource:

    ...    del_timer(&t);    X_Release_Resources( );    ...

In multiprocessor systems, however, this code is not safe because the timer function might already be running on another CPU when del_timer( ) is invoked. As a result, resources may be released while the timer function is still acting on them. To avoid this kind of race condition, the kernel offers the del_timer_sync( ) function. It removes the timer from the list, and then it checks whether the timer function is executed on another CPU; in such a case, del_timer_sync( ) waits until the timer function terminates.


又回头翻看了一下ULK3,我觉得里面这一段已经讲得很清楚了……

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
8 [报告]
发表于 2010-12-01 15:49 |只看该作者
回复 7# kouu
我也明白这段话的意思。
问题是,上面我列出的代码,按照ULK3的理论,应该使用del_timer_sync的,如果使用del_timer是会有问题的。但是为什么我使用del_timer却没有出问题啊?

论坛徽章:
0
9 [报告]
发表于 2010-12-01 17:37 |只看该作者
我想你没明白这段文字的意思……

上面所说的是,del_timer(&t)之后,会调用X_Release_Resources( )来释放某些资源。而这些资源会被t.function使用。
由于del_timer调用之后,t.function可能正在其他CPU上运行,可能正在访问这些资源。而与此同时,这些资源又正在被X_Release_Resources释放……

在这样的情况下,才应该使用del_timer_sync,而不是del_timer。
如果你在del_timer之后不去释放资源,t.function需要访问的资源都正常,那么又怎么会崩溃呢?而你的测试代码不就没有牵涉资源释么~

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
10 [报告]
发表于 2010-12-01 20:00 |只看该作者
回复 9# kouu
多谢。终于搞明白了。原来意思是指del_timer()执行后,释放资源导致竞态问题。
我一直是以为在del_timer()这个函数中会释放某些内核自己创建定时器时分配的资源,从而导致竞态呢。呵呵多谢了
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP