红联Linux门户
Linux帮助

结构体的问题

发布时间:2010-08-31 15:56:18来源:红联作者:wucongdonglai
最近看定时器,遇到一种情况,比较不解,简化后来说就是:
先定义一个定时器:
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)吗?
文章评论

共有 19 条评论

  1. deepwhite 于 2010-09-03 08:45:54发表:

    引用:
    16# deepwhite
    我觉得内核也不至于犯这错误,所以我的意思是:在结构体中包含指针函数时,其指针函数初始化时所指向的函数与结构体对象是否存在无关?
    wucongdonglai 发表于 2010-9-3 08:41

    当然了。

  2. wucongdonglai 于 2010-09-03 08:41:38发表:

    16# deepwhite
    我觉得内核也不至于犯这错误,所以我的意思是:在结构体中包含指针函数时,其指针函数初始化时所指向的函数与结构体对象是否存在无关?

  3. wucongdonglai 于 2010-09-03 08:39:32发表:

    15# shenhao0129
    del_singleshot_timer_sync(&timer)函数使定时器无效,并等待直到定时器函数结束

  4. pl_014 于 2010-09-03 07:10:58发表:

    引用:
    "pl_104" 的帖子: 教科书中说标准 C 中没有对象, struct 中也不能有函数。但是如
    果在 struct 中加入一些函数指针呢? 内核在很多的 struct 中将函数指针作为了成员
    变量,通过这种方式实现了 “面向对象”。感兴趣的话可以多看看内核代码。我最近也
    在看。不知不觉中学习了不少的东西。
    deepwhite 发表于 2010-9-1 09:28


    引用:
    C语言有对象的,只是和C++中的意义不同,

    C993.14
    1 object
    region of data storage in the execution environment, the contents of which can represent
    values
    奶茶dsk 发表于 2010-9-1 13:28



    看来我对c的理解还很浅薄,就你奶茶dsk说的那样,c里面的对象和c++里面的对象的意义不同,也许是我看别人比较片面的语论看多了,都说什么c不是面向对象的,c++才是面向对象的,所以,我就一直以为c里面没有面向对象一说了。

  5. 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 的处理结果。


    不会出现你说的那种“删除定时器后再去调用这个定时器内的函数 ”的情况。

    内核不会犯这种错误。

  6. shenhao0129 于 2010-09-01 20:27:10发表:

    你确实那个是删除定时器?

  7. 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)删除定时器了嘛

  8. 奶茶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]

  9. 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 中将函数指针作为了成员
    变量,通过这种方式实现了 “面向对象”。感兴趣的话可以多看看内核代码。我最近也
    在看。不知不觉中学习了不少的东西。

  10. deepwhite 于 2010-09-01 09:12:35发表:

    引用:
    4# deepwhite
    问题是Linux内核就在干这事,它先把定时器对象删除后,再去调用那指针所指向的函数,所以我才纳闷啊
    wucongdonglai 发表于 2010-9-1 08:50

    仔细看代码吧。

  11. wucongdonglai 于 2010-09-01 08:56:36发表:

    5# pl_014
    我觉得也是,这能保证结果的正确吗?我也很怀疑

  12. wucongdonglai 于 2010-09-01 08:54:48发表:

    6# shenhao0129
    我的理解和你一样,所以我对这不理解,这是内核的一个定时器方面的代码,C++里一般也不这么干的,至少我做应用程序开发从不这么干

  13. wucongdonglai 于 2010-09-01 08:52:26发表:

    3# pl_014
    算是c的吧,但不是标准c,我漏打了2分号

  14. wucongdonglai 于 2010-09-01 08:50:58发表:

    4# deepwhite
    问题是Linux内核就在干这事,它先把定时器对象删除后,再去调用那指针所指向的函数,所以我才纳闷啊

  15. shenhao0129 于 2010-08-31 23:46:41发表:

    你定义的void process_timeout(unsigned long *base) 这个函数与你定义的结构体有什么关系?
    函数应该是可以调用的,但是传给函数的参数由于你已经删除了那个对象,那么这个对象中的Base参数就应该不能再调用了吧?貌似我理解的是这样的,对于C++不是非常的了解

  16. pl_014 于 2010-08-31 20:54:51发表:

    [i=s] 本帖最后由 pl_014 于 2010-8-31 20:55 编辑 [/i]

    首先,要说明一点,结构体里面是不包含函数的,所以删除了一个结构体变量,应该不会影响函数的调用的,除非这个结构体是全局的。
    其次,楼主的意思可能是用结构体的某一个成员作为函数的传入值,但如果要表式结构体的某个成员,必须有成员选则的符号,即"."或"->"
    但是,对于这个程序,我所了解的并不多,虽然调用这个函数还是可以的,但并不能保证正确调用该函数

  17. deepwhite 于 2010-08-31 20:53:42发表:

    [i=s] 本帖最后由 deepwhite 于 2010-8-31 20:55 编辑 [/i]

    问题问的,让人不得要领。或者是我理解不了你的问题。

    能调是能调,你别通过计时器里面的函数指针而直接调用那个函数,并传给合适的参数就可以。

    可是问题是,离开了记时计这个数据结构,那个单个的函数还有什么用呢?你调他做什么呢?再说内核代码,普通用户根本不会接触到,除非你想自己折腾折腾,否则好好的定时器结构,不会无端消失。

  18. pl_014 于 2010-08-31 20:48:35发表:

    引用:
    请问这是shell? 还是C?
    vastmy 发表于 2010-8-31 20:00


    也不好确定,因为标准的C每句后面都应该有一个分号,这段代码好几处都没有。

    另外,标准C里面应该没有对象一说

    对于函数指针的赋值,这种方法似乎也不是标准C的方法


    对于是否是shell,不好说,我没遇到过这种脚本

  19. vastmy 于 2010-08-31 20:00:58发表:

    请问这是shell? 还是C?