对于每个联机cpu,获取指向cpuinfo\ux86的指针
linux内核中的cpuinfo模块使用以下代码获取指向cpu的指针:对于每个联机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); 启动
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();