对于每个联机cpu,获取指向cpuinfo\ux86的指针

对于每个联机cpu,获取指向cpuinfo\ux86的指针,c,linux,linux-kernel,linux-device-driver,cpu,C,Linux,Linux Kernel,Linux Device Driver,Cpu,linux内核中的cpuinfo模块使用以下代码获取指向cpu的指针: ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) { // (...) struct seq_file *m = file->private_data; void *p; // (...) p = m->op->start(m, &pos); 启动

linux内核中的cpuinfo模块使用以下代码获取指向cpu的指针:

ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
    // (...)
    struct seq_file *m = file->private_data;
    void *p;
    // (...)
    p = m->op->start(m, &pos);
启动方法见程序c:

static void *c_start(struct seq_file *m, loff_t *pos)
{
    *pos = cpumask_next(*pos - 1, cpu_online_mask);
    if ((*pos) < nr_cpu_ids)
        return &cpu_data(*pos);
    return NULL;
}
将指针指定为指向cpuinfo_x86的指针:

但是,如果我在代码(linux内核模块)中做了类似的事情:

    get_online_cpus();
    pos = kmalloc( sizeof( loff_t), GFP_KERNEL);
    *pos = 0;
    *pos = cpumask_next(*pos - 1, cpu_online_mask);
    if ( (*pos) < nr_cpu_ids)
    {
         c = &cpu_data(*pos);
         cpu = c->cpu_index;  // SIGSEGV !
    }
为什么我会得到SIGSEGV?我知道vfs传递给cpuinfo的文件是特殊的顺序文件,但它似乎与
cpu\u数据
宏无关。到目前为止,我唯一能看到的区别是,在第一种情况下,指针被传递到函数,然后它被分配到该函数中,因此我们有一个堆栈框架,等等。这与优化有关吗

如果我在单独的函数中执行赋值,则它会起作用:

static void*
mpsrv_get_cpu_ptr( loff_t *pos)
{
    *pos = cpumask_next(*pos - 1, cpu_possible_mask);

    if ( (*pos) < nr_cpu_ids)
        return &cpu_data(*pos);

    return NULL;
}

static void 
mpsrv_stat_cpu( struct mpsrv_cpu_info *cpu_info, void *v)
{
    struct cpuinfo_x86 *c = v;  // OK
    unsigned int cpu;

    cpu = c->cpu_index;         // OK
    // (...)
}

// code

    get_online_cpus();
    pos = cpu_n = 0;

    while ( ( p = mpsrv_get_cpu_ptr( &pos)))
    {
        mpsrv_stat_cpu( cpu_info, p);

        ++cpu_n;
        ++pos;
    }

    put_online_cpus(); 
静态无效*
mpsrv_get_cpu_ptr(loff_t*pos)
{
*pos=cpumask\u next(*pos-1,cpu\u可能的\u掩码);
如果((*pos)cpu\U索引;//确定
// (...)
}
//代码
联机获取CPU();
pos=cpu\u n=0;
而((p=mpsrv\u get\u cpu\u ptr(&pos)))
{
mpsrv_stat_cpu(cpu_info,p);
++中央处理器;
++pos;
}
将_联机_CPU();
c中的内核代码还返回一个指向cpuinfo_x86的指针,该指针是在单独的函数c_start()中获得的。
如果需要其他信息,请告诉我。谢谢。

我想您有多个内核。这是否会发生在所有内核上,或者它是否可能在第一个内核上工作而在其他内核上失败(可能正在休眠)?@VAndrei是的,它是在4个内核上的Intel Xeon E5620,2.4GHz。此代码正在虚拟机上运行。我远程调试。如果它不是在功能中运行,它在第一个内核上也会失败。我用get_online_cpus()/put_online_cpus()介绍了cpu掩码的获取。最近,我发现用于通过以太网进行调试的kgdb模块kgdboe.ko被插入内核进行调试,它禁用了所有三个内核,因此在调试时我始终只使用CPU0
    get_online_cpus();
    pos = kmalloc( sizeof( loff_t), GFP_KERNEL);
    *pos = 0;
    *pos = cpumask_next(*pos - 1, cpu_online_mask);
    if ( (*pos) < nr_cpu_ids)
    {
         c = &cpu_data(*pos);
         cpu = c->cpu_index;  // SIGSEGV !
    }
for_each_online_cpu( cpuid)
{
    c = &cpu_data(cpuid);
static void*
mpsrv_get_cpu_ptr( loff_t *pos)
{
    *pos = cpumask_next(*pos - 1, cpu_possible_mask);

    if ( (*pos) < nr_cpu_ids)
        return &cpu_data(*pos);

    return NULL;
}

static void 
mpsrv_stat_cpu( struct mpsrv_cpu_info *cpu_info, void *v)
{
    struct cpuinfo_x86 *c = v;  // OK
    unsigned int cpu;

    cpu = c->cpu_index;         // OK
    // (...)
}

// code

    get_online_cpus();
    pos = cpu_n = 0;

    while ( ( p = mpsrv_get_cpu_ptr( &pos)))
    {
        mpsrv_stat_cpu( cpu_info, p);

        ++cpu_n;
        ++pos;
    }

    put_online_cpus();