Linux内核API set_cpus_allowed_ptr

set_cpus_allowed_ptr函数功能描述:此函数用于改变进程的执行CPU,即改变进程执行时所占用的CPU资源。

set_cpus_allowed_ptr文件包含

#include <linux/sched.h>

set_cpus_allowed_ptr函数定义

在内核源码中的位置:

linux-3.19.3/include/linux/sched.h, linux-3.19.3/kernel/sched/core.c

函数定义格式:

#ifdef CONFIG_SMP
    extern int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask);
#else
    static inline int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask)
    {
        if (! cpumask_test_cpu(0, new_mask))
            return -EINVAL;
        return 0;
    }
#endif

set_cpus_allowed_ptr输入参数说明

  • 此函数的第一个参数是struct task_struct结构体类型的指针,保存进程的描述符信息,此结构体的定义较复杂,内核定义中的解释足够清晰,结构体定义参见文件linux-3.19.3/include/linux/sched.h。
  • 此函数的第二个参数是struct cpumask结构体类型的指针,其实是一个无符号的长整型的数组,数组的大小由当前内核所定义的CPU数决定,与NR_CPUS有关,具体定义见文件linux-3.19.3/include/linux/cpumask.h,如下:
typedef struct cpumask { DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t;

其中DECLARE_BITMAP的定义如下:

#define DECLARE_BITMAP(name, bits) \
    unsigned long name[BITS_TO_LONGS(bits)]

其中BITS_TO_LONGS的定义如下:

#define BITS_TO_LONGS(bits)\
    (((bits)+BITS_PRE_LONGS-1)/BITS_PRE_LONGS)

数组中的每一位代表一个CPU标志位,数组的下标与相应的CPU的值对应,如果数组中的某一位是1代表当前CPU被设置在此CPU掩码变量中。在此函数中此参数保存将设置的进程的新的CPU值。

set_cpus_allowed_ptr返回参数说明

此函数的返回结果是int型的变量,可能的取值是0、-22,其中返回0代表改变进程执行的CPU值成功,返回-22代表改变进程执行的CPU值失败。

set_cpus_allowed_ptr实例解析

编写测试文件:set_cpus_allowed_ptr.c

头文件引用及全局变量定义:

/*头文件引用*/
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/pid.h>
#include <linux/wait.h>
#include <linux/cpumask.h>
#include <linux/kthread.h>
MODULE_LICENSE("GPL");

/*全局变量定义*/
static int cpu;                                      //保存进程的调度CPU值
struct task_struct * old_thread;

子进程处理函数定义:

int my_function(void * argc)
{
    int data=-1;                                     //保存函数返回结果
    cpumask_var_t mask;                              //CPU掩码变量
    alloc_cpumask_var(&mask, GFP_KERNEL);            //为CPU掩码变量开辟内存空间
    cpumask_set_cpu(cpu, mask);                      //初始化CPU掩码变量
    printk("in the kernel thread function! \n");
    printk("the current pid is:%d\n", current->pid);  //显示当前进程的PID值
    data=set_cpus_allowed_ptr(old_thread, mask); // 调用函数更改父进程的所在CPU值
    printk("the return result of the set_cpus_allowed_ptr is:%d\n", data);
                                                     //显示函数调用返回结果
    printk("out the kernel thread function\n");
    return 0;
}

模块加载函数定义:

static int __init set_cpus_allowed_ptr_init(void)
{
/*局部变量定义*/
struct task_struct * result;
long result1;
struct thread_info * info;
wait_queue_head_t head;
wait_queue_t data;
printk("into set_cpus_allowed_ptr_init.\n");
old_thread = current;
info=current_thread_info( ); //获取当前进程的进程信息
result=kthread_create_on_node(my_function, NULL, -1, "set_cpus_allowed_ptr");
                              // 创建新进程
wake_up_process(result);

cpu=(info->cpu==0)?1:0;       //给全局变量赋值,使其值与当前进程的CPU值不同
printk("the cpu of the current thread is:%d\n", info->cpu);
                              // 显示当前进程所在CPU的值
init_waitqueue_head(&head);  //初始化等待队列的头元素
init_waitqueue_entry(&data, current);     //用当前进程初始化等待队列中的一个元素
add_wait_queue(&head, &data); //将当前进程加入等待队列中
result1=schedule_timeout_uninterruptible(100); //将等待队列置于不可中断的等待状态
printk("the new cpu of the current thread is:%d\n", info->cpu);
                              // 显示当前进程的新的CPU值
printk("the pid of new thread is :%d\n", result->pid);
                              //显示函数kthread_create_on_node( )的返回结果pid
printk("the return result of the schedule_timeout_uninterruptible is:%ld\n", result1);
                      //显示函数schedule_timeout_uninterruptible( )的返回结果
printk("the current pid is:%d\n", current->pid); //显示当前进程的PID值
printk("out set_cpus_allowed_ptr_init.\n");
return 0;
}

模块退出函数定义:

static void __exit set_cpus_allowed_ptr_exit(void)
{
    printk("Goodbye set_cpus_allowed_ptr\n");
}

模块加载、退出函数调用:

module_init(set_cpus_allowed_ptr_init);
module_exit(set_cpus_allowed_ptr_exit);

实例运行结果及分析:

首先编译模块,执行命令insmod set_cpus_allowed_ptr.ko插入内核模块,然后输入命令dmesg -c查看模块插入结果,会出现如图所示的结果。

Linux内核API set_cpus_allowed_ptr

结果分析:

由上图可以得出在子进程执行之前父进程的CPU值为0,在子进程处理函数中调用了函数set_cpus_allowed_ptr( ),重新设定父进程执行的CPU值,此值与先前的CPU值不同,由函数set_cpus_allowed_ptr( )的返回结果是0可以推断设置父进程的CPU值成功。子进程结束之后,在父进程中重新输出CPU值,发现CPU值变为1,说明了函数set_cpus_allowed_ptr( )成功改变了父进程的CPU值。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程