91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

把進(jìn)程綁定到某個(gè) CPU 上運(yùn)行是怎么實(shí)現(xiàn)?

Linux愛好者 ? 來源:Linux內(nèi)核那些事 ? 作者:songsong001 ? 2021-07-02 09:55 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

昨天在群里有朋友問:把進(jìn)程綁定到某個(gè) CPU 上運(yùn)行是怎么實(shí)現(xiàn)的。

首先,我們先來了解下將進(jìn)程與 CPU 進(jìn)行綁定的好處。

進(jìn)程綁定 CPU 的好處:在多核 CPU 結(jié)構(gòu)中,每個(gè)核心有各自的L1、L2緩存,而L3緩存是共用的。如果一個(gè)進(jìn)程在核心間來回切換,各個(gè)核心的緩存命中率就會(huì)受到影響。相反如果進(jìn)程不管如何調(diào)度,都始終可以在一個(gè)核心上執(zhí)行,那么其數(shù)據(jù)的L1、L2 緩存的命中率可以顯著提高。

所以,將進(jìn)程與 CPU 進(jìn)行綁定可以提高 CPU 緩存的命中率,從而提高性能。而進(jìn)程與 CPU 綁定被稱為:CPU 親和性。

設(shè)置進(jìn)程的 CPU 親和性前面介紹了進(jìn)程與 CPU 綁定的好處后,現(xiàn)在來介紹一下在 Linux 系統(tǒng)下怎么將進(jìn)程與 CPU 進(jìn)行綁定的(也就是設(shè)置進(jìn)程的 CPU 親和性)。

Linux 系統(tǒng)提供了一個(gè)名為 sched_setaffinity 的系統(tǒng)調(diào)用,此系統(tǒng)調(diào)用可以設(shè)置進(jìn)程的 CPU 親和性。我們來看看 sched_setaffinity 系統(tǒng)調(diào)用的原型:

int sched_setaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *mask);

下面介紹一下 sched_setaffinity 系統(tǒng)調(diào)用各個(gè)參數(shù)的作用:

pid:進(jìn)程ID,也就是要進(jìn)行綁定 CPU 的進(jìn)程ID。

cpusetsize:mask 參數(shù)所指向的 CPU 集合的大小。

mask:與進(jìn)程進(jìn)行綁定的 CPU 集合(由于一個(gè)進(jìn)程可以綁定到多個(gè) CPU 上運(yùn)行)。

參數(shù) mask 的類型為 cpu_set_t,而 cpu_set_t 是一個(gè)位圖,位圖的每個(gè)位表示一個(gè) CPU。:

例如,將 cpu_set_t 的第0位設(shè)置為1,表示將進(jìn)程綁定到 CPU0 上運(yùn)行,當(dāng)然我們可以將進(jìn)程綁定到多個(gè) CPU 上運(yùn)行。

我們通過一個(gè)例子來介紹怎么通過 sched_setaffinity 系統(tǒng)調(diào)用來設(shè)置進(jìn)程的 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)

{

cpu_set_t cpuset;

CPU_ZERO(&cpuset); // 初始化CPU集合,將 cpuset 置為空

CPU_SET(2, &cpuset); // 將本進(jìn)程綁定到 CPU2 上

// 設(shè)置進(jìn)程的 CPU 親和性

if (sched_setaffinity(0, sizeof(cpuset), &cpuset) == -1) {

printf(“Set CPU affinity failed, error: %s

”, strerror(errno));

return -1;

}

return 0;

}

CPU 親和性實(shí)現(xiàn)知道怎么設(shè)置進(jìn)程的 CPU 親和性后,現(xiàn)在我們來分析一下 Linux 內(nèi)核是怎樣實(shí)現(xiàn) CPU 親和性功能的。

本文使用的 Linux 內(nèi)核版本為 2.6.23

Linux 內(nèi)核為每個(gè) CPU 定義了一個(gè)類型為 struct rq 的 可運(yùn)行的進(jìn)程隊(duì)列,也就是說,每個(gè) CPU 都擁有一個(gè)獨(dú)立的可運(yùn)行進(jìn)程隊(duì)列。

一般來說,CPU 只會(huì)從屬于自己的可運(yùn)行進(jìn)程隊(duì)列中選擇一個(gè)進(jìn)程來運(yùn)行。也就是說,CPU0 只會(huì)從屬于 CPU0 的可運(yùn)行隊(duì)列中選擇一個(gè)進(jìn)程來運(yùn)行,而絕不會(huì)從 CPU1 的可運(yùn)行隊(duì)列中獲取。

所以,從上面的信息中可以分析出,要將進(jìn)程綁定到某個(gè) CPU 上運(yùn)行,只需要將進(jìn)程放置到其所屬的 可運(yùn)行進(jìn)程隊(duì)列 中即可。

下面我們來分析一下 sched_setaffinity 系統(tǒng)調(diào)用的實(shí)現(xiàn),sched_setaffinity 系統(tǒng)調(diào)用的調(diào)用鏈如下:

sys_sched_setaffinity()

└→ sched_setaffinity()

└→ set_cpus_allowed()

└→ migrate_task()

從上面的調(diào)用鏈可以看出,sched_setaffinity 系統(tǒng)調(diào)用最終會(huì)調(diào)用 migrate_task 函數(shù)來完成進(jìn)程與 CPU 進(jìn)行綁定的工作,我們來分析一下 migrate_task 函數(shù)的實(shí)現(xiàn):

static int

migrate_task(struct task_struct *p, int dest_cpu, struct migration_req *req)

{

struct rq *rq = task_rq(p);

// 情況1:

// 如果進(jìn)程還沒有在任何運(yùn)行隊(duì)列中

// 那么只需要將進(jìn)程的 cpu 字段設(shè)置為 dest_cpu 即可

if (!p-》se.on_rq && !task_running(rq, p)) {

set_task_cpu(p, dest_cpu);

return 0;

}

// 情況2:

// 如果進(jìn)程已經(jīng)在某一個(gè) CPU 的可運(yùn)行隊(duì)列中

// 那么需要將進(jìn)程從之前的 CPU 可運(yùn)行隊(duì)列中遷移到新的 CPU 可運(yùn)行隊(duì)列中

// 這個(gè)遷移過程由 migration_thread 內(nèi)核線程完成

// 構(gòu)建進(jìn)程遷移請(qǐng)求

init_completion(&req-》done);

req-》task = p;

req-》dest_cpu = dest_cpu;

list_add(&req-》list, &rq-》migration_queue);

return 1;

}

我們先來介紹一下 migrate_task 函數(shù)各個(gè)參數(shù)的意義:

p:要設(shè)置 CPU 親和性的進(jìn)程描述符。

dest_cpu:綁定的 CPU 編號(hào)。

req:進(jìn)程遷移請(qǐng)求對(duì)象(下面會(huì)介紹)。

所以,migrate_task 函數(shù)的作用就是將進(jìn)程描述符為 p 的進(jìn)程綁定到編號(hào)為 dest_cpu 的目標(biāo) CPU 上。

migrate_task 函數(shù)主要分兩種情況來將進(jìn)程綁定到某個(gè) CPU 上:

情況1:如果進(jìn)程還沒有在任何 CPU 的可運(yùn)行隊(duì)列中(不可運(yùn)行狀態(tài)),那么只需要將進(jìn)程描述符的 cpu 字段設(shè)置為 dest_cpu 即可。當(dāng)進(jìn)程變?yōu)榭蛇\(yùn)行時(shí),會(huì)根據(jù)進(jìn)程描述符的 cpu 字段來自動(dòng)放置到對(duì)應(yīng)的 CPU 可運(yùn)行隊(duì)列中。

情況2:如果進(jìn)程已經(jīng)在某個(gè) CPU 的可運(yùn)行隊(duì)列中,那么需要將進(jìn)程從之前的 CPU 可運(yùn)行隊(duì)列中遷移到新的 CPU 可運(yùn)行隊(duì)列中。遷移過程由 migration_thread 內(nèi)核線程完成,migrate_task 函數(shù)只是構(gòu)建一個(gè)進(jìn)程遷移請(qǐng)求,并通知 migration_thread 內(nèi)核線程有新的遷移請(qǐng)求需要處理。

而進(jìn)程遷移過程由 __migrate_task 函數(shù)完成,我們來看看 __migrate_task 函數(shù)的實(shí)現(xiàn):

static int

__migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)

{

struct rq *rq_dest, *rq_src;

int ret = 0, on_rq;

。。。

rq_src = cpu_rq(src_cpu); // 進(jìn)程所在的原可運(yùn)行隊(duì)列

rq_dest = cpu_rq(dest_cpu); // 進(jìn)程希望放置的目標(biāo)可運(yùn)行隊(duì)列

。。。

on_rq = p-》se.on_rq; // 進(jìn)程是否在可運(yùn)行隊(duì)列中(可運(yùn)行狀態(tài))

if (on_rq)

deactivate_task(rq_src, p, 0); // 把進(jìn)程從原來的可運(yùn)行隊(duì)列中刪除

set_task_cpu(p, dest_cpu);

if (on_rq) {

activate_task(rq_dest, p, 0); // 把進(jìn)程放置到目標(biāo)可運(yùn)行隊(duì)列中

。。。

}

。。。

return ret;

}

__migrate_task 函數(shù)主要完成以下兩個(gè)工作:

把進(jìn)程從原來的可運(yùn)行隊(duì)列中刪除。

把進(jìn)程放置到目標(biāo)可運(yùn)行隊(duì)列中。

其工作過程如下圖所示(將進(jìn)程從 CPU0 的可運(yùn)行隊(duì)列遷移到 CPU3 的可運(yùn)行隊(duì)列中):

如上圖所示,進(jìn)程原本在 CPU0 的可運(yùn)行隊(duì)列中,但由于重新將進(jìn)程綁定到 CPU3,所以需要將進(jìn)程從 CPU0 的可運(yùn)行隊(duì)列遷移到 CPU3 的可運(yùn)行中。

遷移過程首先將進(jìn)程從 CPU0 的可運(yùn)行隊(duì)列中刪除,然后再將進(jìn)程插入到 CPU3 的可運(yùn)行隊(duì)列中。

當(dāng) CPU 要運(yùn)行進(jìn)程時(shí),首先從它所屬的可運(yùn)行隊(duì)列中挑選一個(gè)進(jìn)程,并將此進(jìn)程調(diào)度到 CPU 中運(yùn)行。

總結(jié)從上面的分析可知,其實(shí)將進(jìn)程綁定到某個(gè) CPU 只是將進(jìn)程放置到 CPU 的可運(yùn)行隊(duì)列中。

由于每個(gè) CPU 都有一個(gè)可運(yùn)行隊(duì)列,所以就有可能會(huì)出現(xiàn) CPU 間可運(yùn)行隊(duì)列負(fù)載不均衡問題。如 CPU0 可運(yùn)行隊(duì)列中的進(jìn)程比 CPU1 可運(yùn)行隊(duì)列多非常多,從而導(dǎo)致 CPU0 的負(fù)載非常高,而 CPU1 負(fù)載非常低的情況。

當(dāng)出現(xiàn)上述情況時(shí),就需要對(duì) CPU 間的可運(yùn)行隊(duì)列進(jìn)行重平衡操作,有興趣的可以自行閱讀源碼或參考相關(guān)資料。

編輯:jq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 內(nèi)核
    +關(guān)注

    關(guān)注

    4

    文章

    1468

    瀏覽量

    42874
  • cpu
    cpu
    +關(guān)注

    關(guān)注

    68

    文章

    11279

    瀏覽量

    224964
  • Linux
    +關(guān)注

    關(guān)注

    88

    文章

    11760

    瀏覽量

    219020

原文標(biāo)題:圖解:進(jìn)程怎么綁定 CPU

文章出處:【微信號(hào):LinuxHub,微信公眾號(hào):Linux愛好者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    飛凌嵌入式ElfBoard-進(jìn)程之什么是進(jìn)程

    ID,簡(jiǎn)稱 PID),用來標(biāo)識(shí)當(dāng)前的進(jìn)程,區(qū)分不同的進(jìn)程。這使得系統(tǒng)能夠有效地管理多個(gè)并發(fā)運(yùn)行進(jìn)程,避免混淆。在Linux命令行中直接使用ps命令即可查看到
    發(fā)表于 03-02 08:49

    操作系統(tǒng)運(yùn)行機(jī)制

    不同的層次。一些與硬件關(guān)聯(lián)較緊密的模塊,諸如時(shí)鐘管理、中斷處理、設(shè)備驅(qū)動(dòng)等處于最底層。其次是運(yùn)行頻率較髙的程序,諸如進(jìn)程管理、存儲(chǔ)器管理和設(shè)備管理等。這兩部分內(nèi)容構(gòu)成了操作系統(tǒng)的內(nèi)核。這部分內(nèi)容的指令
    發(fā)表于 01-15 07:12

    進(jìn)程概念和特征

    進(jìn)程的基本情況和運(yùn)行狀態(tài),進(jìn)而控制和管理進(jìn)程。相應(yīng)地,由程序段、相關(guān)數(shù)據(jù)段和PCB三部分構(gòu)成了進(jìn)程映像(進(jìn)程實(shí)體)。所謂創(chuàng)建
    發(fā)表于 01-15 06:39

    進(jìn)程通信

    直接消息發(fā)送給接收進(jìn)程,并將它掛在接收進(jìn)程的消息緩沖隊(duì)列上,接收進(jìn)程從消息緩沖隊(duì)列中取得消息。   2) 間接通信方式:發(fā)送進(jìn)程
    發(fā)表于 01-15 06:16

    進(jìn)程的控制

    是:   1. 找到將要被阻塞進(jìn)程的標(biāo)識(shí)號(hào)對(duì)應(yīng)的PCB。   2. 若該進(jìn)程運(yùn)行狀態(tài),則保護(hù)其現(xiàn)場(chǎng),將其狀態(tài)轉(zhuǎn)為阻塞狀態(tài),停止運(yùn)行。   3.
    發(fā)表于 01-15 06:05

    深入Linux內(nèi)核:進(jìn)程調(diào)度的核心邏輯與實(shí)現(xiàn)細(xì)節(jié)

    在Linux系統(tǒng)中,進(jìn)程調(diào)度就像一位精明的“CPU管理員”——它決定著哪個(gè)進(jìn)程能優(yōu)先使用CPU,多久切換一次進(jìn)程,如何平衡系統(tǒng)響應(yīng)速度與資源
    的頭像 發(fā)表于 12-24 07:05 ?4303次閱讀
    深入Linux內(nèi)核:<b class='flag-5'>進(jìn)程</b>調(diào)度的核心邏輯與<b class='flag-5'>實(shí)現(xiàn)</b>細(xì)節(jié)

    解析Linux的進(jìn)程、線程和協(xié)程

    一、基礎(chǔ)概念 進(jìn)程(Process) 進(jìn)程是計(jì)算機(jī)中運(yùn)行的程序的實(shí)例,它是操作系統(tǒng)中最基本的執(zhí)行單元之一。每個(gè)進(jìn)程都有自己的獨(dú)立內(nèi)存空間、系統(tǒng)資源和代碼執(zhí)行流。這意味著一個(gè)
    發(fā)表于 12-22 11:00

    嵌入式基礎(chǔ)知識(shí)-系統(tǒng)調(diào)度

    被強(qiáng)制剝奪CPU使用權(quán) 2、進(jìn)程切換 進(jìn)程切換是指,操作系統(tǒng)為了控制進(jìn)程的執(zhí)行,必須有能力掛起正在CPU
    發(fā)表于 12-16 08:15

    在極海APM32系列MCU中如何代碼重定位SDRAM運(yùn)行

    在有些情況下,我們想要把代碼放到SDRAM運(yùn)行。下面介紹在APM32的MCU中,如何代碼重定位SDRAM運(yùn)行。對(duì)于不同APM32系列的MCU,方法都是一樣的。
    的頭像 發(fā)表于 11-04 09:14 ?5175次閱讀
    在極海APM32系列MCU中如何<b class='flag-5'>把</b>代碼重定位<b class='flag-5'>到</b>SDRAM<b class='flag-5'>運(yùn)行</b>

    時(shí)序約束管腳綁定不成功問題

    {[新手提問]: 關(guān)于引腳綁定問題}在綁定vivado引腳中時(shí),選項(xiàng)中沒有原理圖可綁定的引腳,需要綁定的引腳在l/O Bank88,但是我需要綁定
    發(fā)表于 08-21 17:18

    如何將 UID 代碼綁定 M031 LDROM 和 APROM 固件?

    將 UID 代碼綁定 M031 LDROM 和 APROM 固件
    發(fā)表于 08-20 06:38

    STM32IDE如何設(shè)定代碼ITCM中運(yùn)行

    摸索到了如何將變量定義某個(gè)地址,但是不清楚如何讓代碼在指定RAM中運(yùn)行。按照設(shè)定變量的方式設(shè)定代碼,程序直接進(jìn)入了異常中斷{:16:}。
    發(fā)表于 06-24 06:45

    Linux后臺(tái)進(jìn)程管理詳解

    當(dāng)我們?cè)诮K端或控制臺(tái)工作時(shí),可能不希望由于運(yùn)行一個(gè)作業(yè)而占住了屏幕,因?yàn)榭赡苓€有更重要的事情要做,比如閱讀電子郵件。對(duì)于密集訪問磁盤的進(jìn)程,我們更希望它能夠在每天的非負(fù)荷高峰時(shí)間段運(yùn)行(例如凌晨)。為了使這些
    的頭像 發(fā)表于 04-25 11:04 ?1008次閱讀
    Linux后臺(tái)<b class='flag-5'>進(jìn)程</b>管理詳解

    無法在iMX8啟動(dòng)gpsd:GPSD綁定怎么解決?

    3.19) gpsd:錯(cuò)誤:無法綁定 IPv4 端口 gpsd,地址已在使用 gpsd:ERROR: 也許 gpsd 已經(jīng)在運(yùn)行了! gpsd:錯(cuò)誤:無法綁定
    發(fā)表于 04-04 07:58

    請(qǐng)問如何在Python中實(shí)現(xiàn)多線程與多進(jìn)程的協(xié)作?

    () thread.join() process.join() 我的問題是:**如何合理地組合多線程和多進(jìn)程以獲得更好的性能?**特別是在I/O密集型任務(wù)和CPU密集型任務(wù)混合的情況下,如何避免性能瓶頸,確保程序的高效運(yùn)行? 希
    發(fā)表于 03-11 06:57