最近看定时器,遇到一种情况,比较不解,简化后来说就是:
先定义一个定时器:
struct timer_list{
……
void (*function)(unsigned long)/*所指向的函数*/
tvec_base_t *base;/传递给函数的数据*/
……
}
然后先定义了一个timer_list对象time,然后初始化数据,并把函数
*function=process_timeout(unsigned long *base)
而
void process_timeout(unsigned long *base
{
wake_up_process(*base)
}
然后呢,我先删除对象time,那时候还能调用process_timeout(unsigned long *base)吗?
deepwhite 于 2010-09-03 08:45:54发表:
当然了。
wucongdonglai 于 2010-09-03 08:41:38发表:
16# deepwhite
我觉得内核也不至于犯这错误,所以我的意思是:在结构体中包含指针函数时,其指针函数初始化时所指向的函数与结构体对象是否存在无关?
wucongdonglai 于 2010-09-03 08:39:32发表:
15# shenhao0129
del_singleshot_timer_sync(&timer)函数使定时器无效,并等待直到定时器函数结束
pl_014 于 2010-09-03 07:10:58发表:
看来我对c的理解还很浅薄,就你奶茶dsk说的那样,c里面的对象和c++里面的对象的意义不同,也许是我看别人比较片面的语论看多了,都说什么c不是面向对象的,c++才是面向对象的,所以,我就一直以为c里面没有面向对象一说了。
deepwhite 于 2010-09-01 20:46:30发表:
[i=s] 本帖最后由 deepwhite 于 2010-9-1 21:04 编辑 [/i]
我没仔细看过这个部分的代码和书籍。
但我觉得可能是这样的:
到调度器调度回来执行这个进程的时候,无论定时器是否到时间了,都把这个 Timer 禁用;
如果已经执行过,那么 process_timeout() 就已经被调过了。
而如果没有执行,已经将这个 Timer 禁用,定时器到此打住, process_timeout() 就不会被调用。
最后通过返回值来暗示 timer 的处理函数是否已经执行了。外面调schedule_timeout()的函数就知道了 schedule_timeout中timer 的处理结果。
不会出现你说的那种“删除定时器后再去调用这个定时器内的函数 ”的情况。
内核不会犯这种错误。
shenhao0129 于 2010-09-01 20:27:10发表:
你确实那个是删除定时器?
wucongdonglai 于 2010-09-01 17:33:52发表:
11# deepwhite
我遇到的就是在看深入理解Linux内核的第六章的动态定时器应用之一里看到的,不大明白,去看源码:如下
fastcall signed long __sched schedule_timeout(signed long timeout)
{
struct timer_list timer;
unsigned long expire;
switch (timeout)
{
case MAX_SCHEDULE_TIMEOUT:
/*
* These two special cases are useful to be comfortable
* in the caller. Nothing more. We could take
* MAX_SCHEDULE_TIMEOUT from one of the negative value
* but I' d like to return a valid offset (>=0) to allow
* the caller to do everything it want with the retval.
*/
schedule();
goto out;
default:
/*
* Another bit of PARANOID. Note that the retval will be
* 0 since no piece of kernel is supposed to do a check
* for a negative retval of schedule_timeout() (since it
* should never happens anyway). You just have the printk()
* that will tell you if something is gone wrong and where.
*/
if (timeout < 0)
{
printk(KERN_ERR "schedule_timeout: wrong timeout "
"value %lx from %p\n", timeout,
__builtin_return_address(0));
current->state = TASK_RUNNING;
goto out;
}
}
expire = timeout + jiffies;
init_timer(&timer);
timer.expires = expire;
timer.data = (unsigned long) current;
timer.function = process_timeout;
add_timer(&timer);
schedule();
del_singleshot_timer_sync(&timer);
timeout = expire - jiffies;
out:
return timeout < 0 ? 0 : timeout;
}
那看那后面的可不就是我简化的那部分嘛!
当延时到期之后,函数就要执行所指向的延时函数啊process_timeout啊
但是在那之前不是已经有del_singleshot_timer_sync(&timer)删除定时器了嘛
奶茶dsk 于 2010-09-01 13:28:22发表:
C语言有对象的,只是和C++中的意义不同,
C99[code]3.14
1 object
region of data storage in the execution environment, the contents of which can represent
values[/code]
deepwhite 于 2010-09-01 09:28:43发表:
timer_list 中使用了一个链表头,所有的 timer_list 结构的对象会被挂载到内核的某
个全局链表中去。
我估计你说的移除,只是从内核的全局链表中移除了一个 timer_list ,但是那个全局的
链表中应该还有别的 timer_list 。Linux 内核不会犯这么简单的错误。
还有,“沙发”的问题,应该是 C, 不是 bash ,在内核起来之前, bash 脚本无法运
行。
"pl_104" 的帖子: 教科书中说标准 C 中没有对象, struct 中也不能有函数。但是如
果在 struct 中加入一些函数指针呢? 内核在很多的 struct 中将函数指针作为了成员
变量,通过这种方式实现了 “面向对象”。感兴趣的话可以多看看内核代码。我最近也
在看。不知不觉中学习了不少的东西。
deepwhite 于 2010-09-01 09:12:35发表:
仔细看代码吧。
wucongdonglai 于 2010-09-01 08:56:36发表:
5# pl_014
我觉得也是,这能保证结果的正确吗?我也很怀疑
wucongdonglai 于 2010-09-01 08:54:48发表:
6# shenhao0129
我的理解和你一样,所以我对这不理解,这是内核的一个定时器方面的代码,C++里一般也不这么干的,至少我做应用程序开发从不这么干
wucongdonglai 于 2010-09-01 08:52:26发表:
3# pl_014
算是c的吧,但不是标准c,我漏打了2分号
wucongdonglai 于 2010-09-01 08:50:58发表:
4# deepwhite
问题是Linux内核就在干这事,它先把定时器对象删除后,再去调用那指针所指向的函数,所以我才纳闷啊
shenhao0129 于 2010-08-31 23:46:41发表:
你定义的void process_timeout(unsigned long *base) 这个函数与你定义的结构体有什么关系?
函数应该是可以调用的,但是传给函数的参数由于你已经删除了那个对象,那么这个对象中的Base参数就应该不能再调用了吧?貌似我理解的是这样的,对于C++不是非常的了解
pl_014 于 2010-08-31 20:54:51发表:
[i=s] 本帖最后由 pl_014 于 2010-8-31 20:55 编辑 [/i]
首先,要说明一点,结构体里面是不包含函数的,所以删除了一个结构体变量,应该不会影响函数的调用的,除非这个结构体是全局的。
其次,楼主的意思可能是用结构体的某一个成员作为函数的传入值,但如果要表式结构体的某个成员,必须有成员选则的符号,即"."或"->"
但是,对于这个程序,我所了解的并不多,虽然调用这个函数还是可以的,但并不能保证正确调用该函数
deepwhite 于 2010-08-31 20:53:42发表:
[i=s] 本帖最后由 deepwhite 于 2010-8-31 20:55 编辑 [/i]
问题问的,让人不得要领。或者是我理解不了你的问题。
能调是能调,你别通过计时器里面的函数指针而直接调用那个函数,并传给合适的参数就可以。
可是问题是,离开了记时计这个数据结构,那个单个的函数还有什么用呢?你调他做什么呢?再说内核代码,普通用户根本不会接触到,除非你想自己折腾折腾,否则好好的定时器结构,不会无端消失。
pl_014 于 2010-08-31 20:48:35发表:
也不好确定,因为标准的C每句后面都应该有一个分号,这段代码好几处都没有。
另外,标准C里面应该没有对象一说
对于函数指针的赋值,这种方法似乎也不是标准C的方法
对于是否是shell,不好说,我没遇到过这种脚本
vastmy 于 2010-08-31 20:00:58发表:
请问这是shell? 还是C?