2.9.1 进程的处理器亲和性
设置进程的处理器亲和性,用通俗的话说,就是把进程绑定到某些处理器,只允许进程在某些处理器上执行,默认情况是进程可以在所有处理器上执行。
进程描述符增加了以下两个成员:
include/linux/sched.h
struct task_struct {
…
int nr_cpus_allowed;
cpumask_t cpus_allowed;
…
};
成员cpus_allowed保存允许的处理器掩码,成员nr_cpus_allowed保存允许的处理器数量。
1.应用编程接口
内核提供了两个系统调用。
(1)sched_setaffinity用来设置进程的处理器亲和性掩码。
int sched_setaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask);
(2)sched_getaffinity用来获取进程的处理器亲和性掩码。
int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask);
内核线程可以使用以下函数设置处理器亲和性掩码。
(1)kthread_bind用来把一个刚刚创建的内核线程绑定到一个处理器。
void kthread_bind(struct task_struct *p, unsigned int cpu);
(2)set_cpus_allowed_ptr用来设置内核线程的处理器亲和性掩码。
int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask);
2.使用cpuset配置
管理员可以使用cpuset设置进程的处理器亲和性。cpuset用来控制进程在哪些处理器上执行,以及从哪些内存节点分配内存。cpuset可以单独使用,也可以作为cgroup的一个资源控制器使用(cpuset合并到内核的时间比cgroup早,2.6.12版本引入cpuset,2.6.24版本引入cgroup)。
cpuset在单独使用的时候,可以使用cpuset伪文件系统配置,配置方法如下。
(1)创建目录“/dev/cpuset”。
mkdir /dev/cpuset
(2)把cpuset伪文件系统挂载到目录“/dev/cpuset”下。
mount -t cpuset none /dev/cpuset
(3)创建cpuset,假设名称是“abc”。
cd /dev/cpuset mkdir abc
(4)把处理器分配到cpuset,假设把处理器2和3分配到cpuset abc,需要在目录“/dev/cpuset/abc”下配置。
cd abc echo 2-3 > cpuset.cpus
(5)把线程关联到cpuset,假设把线程10关联到cpuset abc,需要在目录“/dev/cpuset/abc”下配置。
echo 10 > tasks
(6)查看线程10关联的cpuset。
cat /proc/10/cpuset
cgroup已经从版本1(cgroup v1)演进到版本2(cgroup v2),目前cgroup v2不支持cpuset控制器。使用cgroup v1的cpuset控制器的配置方法如下。
(1)在目录“/sys/fs/cgroup”下挂载tmpfs文件系统。
mount -t tmpfs cgroup_root /sys/fs/cgroup
(2)在目录“/sys/fs/cgroup”下创建子目录cpuset。
mkdir /sys/fs/cgroup/cpuset
(3)把cgroup伪文件系统挂载到目录“/sys/fs/cgroup/cpuset”,把cpuset控制器关联到控制组层级树。
mount -t cgroup -o cpuset cpuset /sys/fs/cgroup/cpuset
(4)创建控制组,假设名称是“abc”。
cd /sys/fs/cgroup/cpuset mkdir abc
(5)把处理器分配到控制组,假设把处理器2和3分配到控制组abc,需要在目录“/sys/fs/cgroup/cpuset/abc”下配置。
cd abc echo 2-3 > cpuset.cpus
(6)把线程加入控制组,假设把线程20加入控制组abc。
echo 20 > tasks
(7)也可以把线程组加入控制组,指定线程组中任意一个线程的标识符,就会把线程组的所有线程加入控制组。假设把线程10所属的线程组加入控制组abc。
echo 10 > cgroup.procs
(8)查看线程10关联的cpuset。
cat /proc/10/cpuset