linux内核per_cpu变量学习

#include<linux/percpu.h>
DEFINE_PER_CPU(type, name)
例如:
DEFINE_PER_CPU(int[3], my_percpu_arry)

访问当前处理器的变量版本
get_cpu_var()
put_cpu_var()

访问其它处理器的变量副本
per_cpu(variable, int cpu_id)

动态分配与访问:
void *alloc_percpu(type)
void *__alloc_percpu(size_t size, size_t align)

get_cpu()
put_cpu()
per_cpu_ptr()


模块导出:
EXPORT_PER_CPU_SYMBOL(per_cpu_var)
EXPORT_PER_CPU_SYMBOL_GPL(per_cpu_var)

概念挺多的,还是直接上个例程吧,
用户态例程,开20个线程,调用了ioctl函数,内核态的ioctl里对per-cpu变量进行累加操作,最后在close时打印这个per-cpu变量。

#include<stdio.h>
#include<sys/ioctl.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>
#include<string.h>
#include<unistd.h>
#include<string.h>
#include<pthread.h>
#define NUM_THREADS 20 

// 文件描述符
int fd = 0;

// 多线程调用函数
void *pthread_fx( void *args ) {
    ioctl( fd, 1, 0 );
}

int main() {
    int ret = 0;
    
    // 打开文件
    if((fd = open("/dev/hellodr", O_RDWR)) < 0) {
        printf("%s\n", strerror(errno));
        return -1;
    }

    // 开启多线程
    pthread_t tids[NUM_THREADS];
    for ( int i = 0; i < NUM_THREADS; ++i ) {
        ret = pthread_create( &tids[i], NULL, pthread_fx, NULL );
        if ( ret != 0 ) {
            printf( "pthread_create error: error_code = %d\n", ret );
        }
    }

    // 回收线程资源
    for ( int i = 0; i < NUM_THREADS; ++i ) {
        pthread_join(tids[i], NULL);
    }

    // 关闭文件
    close( fd );
    
    return 0;
}

编译时记得带上-pthread

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>

#define    MAJOR_NUM    231
#define    DEVICE_NAME  "hellodr"
//定义一个per-cpu变量
DEFINE_PER_CPU( long, gUsage ) = 0;
int Open( struct inode *pslINode, struct file *pslFileStruct )
{
    printk( KERN_ALERT DEVICE_NAME " hello open.\n" );
    return(0);
}


ssize_t Write( struct file *pslFileStruct, const char __user *pBuffer, size_t nCount, loff_t *pOffset )
{
    printk( KERN_ALERT DEVICE_NAME " hello write.\n" );
    return(0);
}


int Close( struct inode *pslINode, struct file *pslFileStruct )
{
    int     i       = 0;
    unsigned long   ulBaseAddr  = 0;
    unsigned long   ulOffset    = 0;
    long        *pUsage     = NULL;
    long        usageSum    = 0;

    ulOffset = (unsigned long) (&gUsage);
    for_each_online_cpu( i )
    {
        ulBaseAddr  = __per_cpu_offset[i];
        pUsage      = (long *) (ulBaseAddr + ulOffset);
        usageSum    += (*pUsage);
        printk( KERN_ALERT DEVICE_NAME " pUsage = %lx, *pUsage = %ld\n", (unsigned long) pUsage, *pUsage );
    }
    printk( KERN_ALERT DEVICE_NAME " %ld\n", usageSum );
    return(0);
}


long IOControl( struct file *pslFileStruct, unsigned int uiCmd, unsigned long ulArg )
{
    long *pUsage = NULL;
    /* printk( KERN_ALERT DEVICE_NAME ": pUsage = 0x%lx %lx %ld", (unsigned long) pUsage, (unsigned long) (&gUsage), (*pUsage) ); */
    preempt_disable();
    pUsage = this_cpu_ptr( (long *) (&gUsage) );
    (*pUsage)++;
    preempt_enable();
    return(0);
}


struct file_operations hello_flops = {
    .owner      = THIS_MODULE,
    .open       = Open,
    .write      = Write,
    .release    = Close,
    .unlocked_ioctl = IOControl
};

static int __init hello_init( void )
{
    int ret;

    ret = register_chrdev( MAJOR_NUM, DEVICE_NAME, &hello_flops );
    if ( ret < 0 )
    {
        printk( KERN_ALERT DEVICE_NAME " can't register major number.\n" );
        return(ret);
    }
    printk( KERN_ALERT DEVICE_NAME " initialized.\n" );
    return(0);
}


static void __exit hello_exit( void )
{
    printk( KERN_ALERT DEVICE_NAME " removed.\n" );
    unregister_chrdev( MAJOR_NUM, DEVICE_NAME );
}

module_init( hello_init );
module_exit( hello_exit );
MODULE_LICENSE( "GPL" );
MODULE_AUTHOR( "Sean Depp" );
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD       := $(shell pwd)

obj-m	:=a.o

all:
	make -C $(KERNELDIR) M=$(PWD) modules

clean:
	rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.* .tmp_versions *.mod *.order *.symvers *.dwo

sudo mknod /dev/hellodr c 231 0生成设备节点,
最后运行用户态程序。
在这里插入图片描述
这里应该是有类似于8个cpu在运行per-cpu变量的副本,最后结束时把每个副本的值进行累加,得到最终的值。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值