Linux:查看线程运行于哪个CPU核心上

Linux:查看线程运行于哪个CPU核心上
线程是最小的执行调度单元,线程执行于某个CPU核心之上,或者说某个CPU核心执行此线程。

如何查看某线程运行于哪个CPU核心上呢?

ps -eLF 查找 PSR 字段值

ps -eLF
UID         PID   PPID    LWP  C NLWP    SZ   RSS PSR STIME TTY          TIME CMD
root          1      0      1  0    1  4836  1548   2 Feb25 ?        00:00:02 /sbin/init
root          2      0      2  0    1     0     0   2 Feb25 ?        00:00:00 [kthreadd]
root          3      2      3  0    1     0     0   0 Feb25 ?        00:00:00 [migration/0]
……

#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

void *start_routine(void *arg) {
  const char *msg = "thread: i am thread";
  while (1) {
    write(1, msg, strlen(msg));
    sleep(1);
  }
}

int main() {

  pthread_t tid;
  pthread_create(&tid, NULL, start_routine, NULL);

  const char *msg = "main: i am main\n";
  while (1) {
    write(1, msg, strlen(msg));
    usleep(1000);
  }

  return 0;
}


gcc -o main main.c -lpthread
 ./main
……
main: i am main
main: i am main
thread: i am threadmain: i am main
main: i am main
……

在多CPU系统中,通过sched_setaffinity()可以设置进程的CPU亲和力,使进程绑定在某一个或几个CPU上运行,避免在CPU之间来回切换,从而提高该进程的实时性能。
CPU MASK
cpumask.h中定义了4个全局变量来表示CPU的个数:
cpu_possible_mask:系统中总的CPU核数,初始化时设置
cpu_present_mask: 系统中实际的CPU核数。
cpu_online_mask :能被scheduler使用的CPU核数。
cpu_active_mask :能被migration的CPU核数。
如果CONFIG_HOTPLUG_CPU没有被使能,则,
cpu_present_mask=cpu_possible_mask。
cpu_active_mask =cpu_online_mask 。
同时,进程的task_struct中有一个成员cpus_allowed,表示本进程可以在哪些CPU上运行:

#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

int main(int argc, char **argv)
{
    int cpus = 0;
    int  i = 0;
    cpu_set_t mask;
    cpu_set_t get;

    cpus = sysconf(_SC_NPROCESSORS_ONLN);
    printf("cpus: %d\n", cpus);

    CPU_ZERO(&mask);    /* 初始化set集,将set置为空*/
    /*将本进程绑定到CPU2上*/
    CPU_SET(2, &mask);
    if (sched_setaffinity(0, sizeof(mask), &mask) == -1) {
        printf("Set CPU affinity failue, ERROR:%s\n", strerror(errno));
        return -1; 
    }   

    while(1)
    {
      sleep(1);
    }
       
    return 0;
}

使用ps -eo pid,args,psr命令查看main进程确实在CPU2上运行:

在这里插入图片描述

long sched_setaffinity(pid_t pid, const struct cpumask *in_mask)
{
  cpumask_var_t cpus_allowed, new_mask;
  struct task_struct *p;
  int retval;

  rcu_read_lock();

  p = find_process_by_pid(pid);
  if (!p) {
    rcu_read_unlock();
    return -ESRCH;
  }

  /* Prevent p going away */
  get_task_struct(p);
  rcu_read_unlock();

  if (p->flags & PF_NO_SETAFFINITY) {
    retval = -EINVAL;
    goto out_put_task;
  }
  if (!alloc_cpumask_var(&cpus_allowed, GFP_KERNEL)) {
    retval = -ENOMEM;
    goto out_put_task;
  }
  if (!alloc_cpumask_var(&new_mask, GFP_KERNEL)) {
    retval = -ENOMEM;
    goto out_free_cpus_allowed;
  }
  retval = -EPERM;
  if (!check_same_owner(p)) {
    rcu_read_lock();
    if (!ns_capable(__task_cred(p)->user_ns, CAP_SYS_NICE)) {
      rcu_read_unlock();
      goto out_free_new_mask;
    }
    rcu_read_unlock();
  }

  retval = security_task_setscheduler(p);
  if (retval)
    goto out_free_new_mask;


  cpuset_cpus_allowed(p, cpus_allowed);
  cpumask_and(new_mask, in_mask, cpus_allowed);

  /*
   * Since bandwidth control happens on root_domain basis,
   * if admission test is enabled, we only admit -deadline
   * tasks allowed to run on all the CPUs in the task's
   * root_domain.
   */
#ifdef CONFIG_SMP
  if (task_has_dl_policy(p) && dl_bandwidth_enabled()) {
    rcu_read_lock();
    if (!cpumask_subset(task_rq(p)->rd->span, new_mask)) {
      retval = -EBUSY;
      rcu_read_unlock();
      goto out_free_new_mask;
    }
    rcu_read_unlock();
  }
#endif
again:
  retval = set_cpus_allowed_ptr(p, new_mask);

  if (!retval) {
    cpuset_cpus_allowed(p, cpus_allowed);
    if (!cpumask_subset(new_mask, cpus_allowed)) {
      /*
       * We must have raced with a concurrent cpuset
       * update. Just reset the cpus_allowed to the
       * cpuset's cpus_allowed
       */
      cpumask_copy(new_mask, cpus_allowed);
      goto again;
    }
  }
out_free_new_mask:
  free_cpumask_var(new_mask);
out_free_cpus_allowed:
  free_cpumask_var(cpus_allowed);
out_put_task:
  put_task_struct(p);
  return retval;
}

  • 11
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值