【问题标题】:Pointer value changing across function call指针值在函数调用中发生变化
【发布时间】:2015-06-18 00:28:06
【问题描述】:

我在内核中有以下结构

struct state {
    /* Current algorithm iteration */
    int tune_id;
    /* Thread id */
    pid_t tid;
#ifndef __KERNEL__
    /* Paths */
    char *stats_path;
    char *budget_path;
    char *controller_path;
#endif  /* __KERNEL__ */
    int budget;
    /* Stats */
    struct statistics prev_stats;
    struct parameters current_params;
    u64 cur_time;
    /* Algorithm specific data */
    void *data;
};

struct tuning {
    struct algorithm *algorithm;
    struct state *state;
    struct energy energy;
};

我定义了一个函数tune(),如下:

void tune(struct task_struct *task) {
    struct statistics stats;
    struct state *state;
    get_current_stats(&stats);
    state = task->tuning.state;

    get_current_params(&state->current_params);
    compute_energy(&stats, state);
}

其他函数定义为:

void get_current_params(struct parameters *params)
{
    printk(KERN_DEBUG "get_current_params: parameters:0x%X\n", (unsigned int) params);
    params->cpu_frequency_MHZ = (cpufreq_get(0) + 500) / 1000;
    params->mem_frequency_MHZ = (memfreq_get() + 500) / 1000;
}

void compute_energy(struct statistics *stats, struct state *state)
{
    struct statistics *diffs;
    struct frontier *frontier;
    u64 energy_budget;
    int threshold;

    int i,j;
    struct configuration s;
    struct configuration emin;

#ifdef TIMING
    u64 ns;
    ns = get_thread_time();
 #endif

#ifdef DEBUG
#ifdef __KERNEL__
    printk(KERN_DEBUG "compute_energy: parameters:0x%X\n", (unsigned int) &state->current_params);
#endif  /* __KERNEL__ */
#endif
}

当我调用tune()时,输出如下:

[    7.160139] get_current_params: parameters:0xBF396BA0
[    7.160298] compute_energy: parameters:0xBF396B98

我不明白为什么地址与0x8 不同。 这反过来会导致内核中出现除以 0 异常,因为 struct parameters 的值似乎是 0 而不是 get_current_params 初始化的值

为什么struct state的成员current_params的地址会随着函数调用发生变化?

更新
我已验证此错误仅发生在 PID 0。
查看include/linux/init_task.h,我看到PID 0 是静态初始化的。这是我能在 PID 0 和其他任务之间找到的唯一区别。这会以某种方式对我遇到的问题负责吗?

【问题讨论】:

  • 我已经用函数更新了问题。在打印之前它们并没有真正做太多事情,所以我认为它们没有必要添加。
  • 您提到的 2 个函数传递了 2 个不同的参数。 get_current_params() 收到 struct state->struct parameterscompute_enregy() 收到 struct statistics 参数。显然有 2 个不同的参数,因此有 2 个不同的位置。第二个参数是struct state,还是和struct state-> struct parameters不一样。
  • 我同意传递了不同的参数,但我认为正在打印的成员仍然是相同的......或者我的假设有什么错误?

标签: c linux pointers kernel


【解决方案1】:

就我所见,您说得对,两个地址应该相同。所以只能有一个选择:同时内核中的任务信息发生变化。

考虑到您的代码的这个 sn-p:

void tune(struct task_struct *task) {
    ...
    struct state *state;
    ...
    state = task->tuning.state;

您正在管理两个您可能无法控制的结构(您应该检查一下):

(*task): struct task_struct

(*task->tuning.state): struct state

所以当你在tune() 中打电话时

get_current_params(&state->current_params);
compute_energy(&stats, state);

printk 两个函数之间可能会发生一些事情,所以我认为你必须把注意力放在哪里。 尝试在调用 get_current_params() 之前保存 task->tuning.state,以便在调用 compute_energy() 后检查它是否仍然是相同的值。

希望这会有所帮助。

【讨论】:

  • 你说得很好!两个调用之间可能会发生上下文切换。我将对此进行测试并相应地更新原始问题
  • 我创建了引用当前任务的指针并传递了这些引用,而不是每次都引用task->...。这应该帮助我避免上下文切换带来的复杂性。但是,我仍然遇到同样的问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-14
  • 2023-02-08
相关资源
最近更新 更多