在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

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

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

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

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

Linux愛好者 ? 來源:Linux內(nèi)核那些事 ? 作者:songsong001 ? 2021-07-02 09:55 ? 次閱讀

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

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

進(jìn)程綁定 CPU 的好處:在多核 CPU 結(jié)構(gòu)中,每個核心有各自的L1、L2緩存,而L3緩存是共用的。如果一個進(jìn)程在核心間來回切換,各個核心的緩存命中率就會受到影響。相反如果進(jìn)程不管如何調(diào)度,都始終可以在一個核心上執(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)提供了一個名為 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)用各個參數(shù)的作用:

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

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

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

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

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

我們通過一個例子來介紹怎么通過 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 親和性實現(xiàn)知道怎么設(shè)置進(jìn)程的 CPU 親和性后,現(xiàn)在我們來分析一下 Linux 內(nèi)核是怎樣實現(xiàn) CPU 親和性功能的。

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

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

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

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

下面我們來分析一下 sched_setaffinity 系統(tǒng)調(diào)用的實現(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)用最終會調(diào)用 migrate_task 函數(shù)來完成進(jìn)程與 CPU 進(jìn)行綁定的工作,我們來分析一下 migrate_task 函數(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)行隊列中

// 那么只需要將進(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)在某一個 CPU 的可運(yùn)行隊列中

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

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

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

init_completion(&req-》done);

req-》task = p;

req-》dest_cpu = dest_cpu;

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

return 1;

}

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

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

dest_cpu:綁定的 CPU 編號。

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

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

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

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

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

而進(jìn)程遷移過程由 __migrate_task 函數(shù)完成,我們來看看 __migrate_task 函數(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)行隊列

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

。。。

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

if (on_rq)

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

set_task_cpu(p, dest_cpu);

if (on_rq) {

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

。。。

}

。。。

return ret;

}

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

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

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

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

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

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

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

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

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

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

編輯:jq

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

    關(guān)注

    3

    文章

    1410

    瀏覽量

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

    關(guān)注

    68

    文章

    11038

    瀏覽量

    216024
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11465

    瀏覽量

    212806

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

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

收藏 人收藏

    評論

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

    無法在iMX8啟動gpsd:GPSD綁定怎么解決?

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

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

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

    CPU怎么降頻 bios中如何cpu調(diào)低頻率

    CPU降頻是一種有效的節(jié)能措施,同時也有助于降低設(shè)備的溫度和功耗,提高系統(tǒng)的穩(wěn)定性和使用壽命。以下將詳細(xì)介紹如何在操作系統(tǒng)中、BIOS設(shè)置里以及使用第三方軟件來實現(xiàn)CPU降頻。 一、在操作系統(tǒng)中降低
    的頭像 發(fā)表于 02-01 15:02 ?1.4w次閱讀

    深入解析Linux程序與進(jìn)程

    關(guān)于某個數(shù)據(jù)集合的一次運(yùn)行活動。作為系統(tǒng)進(jìn)行資源分配和調(diào)度的基本單位,是操作系統(tǒng)結(jié)構(gòu)的基礎(chǔ)。 程序與進(jìn)程的關(guān)系 進(jìn)程的狀態(tài) 基礎(chǔ)進(jìn)程狀態(tài) 創(chuàng)
    的頭像 發(fā)表于 12-18 11:01 ?410次閱讀
    深入解析Linux程序與<b class='flag-5'>進(jìn)程</b>

    Linux之CPU調(diào)度策略和CPU親和性

    一、調(diào)度策略 調(diào)度進(jìn)程 單個 CPU一次只能執(zhí)行一個進(jìn)程,雖然 Linux 系統(tǒng)通過使用多任務(wù)同時處理多個進(jìn)程,但當(dāng)多個進(jìn)程同時
    的頭像 發(fā)表于 12-05 16:38 ?999次閱讀
    Linux之<b class='flag-5'>CPU</b>調(diào)度策略和<b class='flag-5'>CPU</b>親和性

    fpga 管腳不讓綁定的問題,綁定時提示: Not assignable

    fpga 管腳不讓綁定的--提示 如下圖: 網(wǎng)上說將復(fù)用管腳設(shè)置成 普通I/O,我這也沒找到我要綁定的管腳,怎么設(shè)置。該管腳是和NOR_Flash相關(guān)的,無法綁定,我想實現(xiàn)掉電存儲一些
    發(fā)表于 12-05 15:30

    怎么綁定IP地址和MAC地址

    本篇文章主要說一說怎么在本地計算機(jī)上綁定IP和MAC地址以及通過路由器綁定IP和MAC地址,并且這兩者綁定可以解決什么問題。 ? 先來說說怎么去綁定 本地計算上
    的頭像 發(fā)表于 12-01 22:48 ?1140次閱讀

    一文搞懂Linux進(jìn)程的睡眠和喚醒

    的代碼和數(shù)據(jù),進(jìn)而去執(zhí)行這個進(jìn)程。下面列舉了一些進(jìn)程狀態(tài): 注意:沒有+時,默認(rèn)是后臺進(jìn)程 進(jìn)程調(diào)度(進(jìn)程狀態(tài)切換)
    發(fā)表于 11-04 15:15

    【軟件干貨】Android應(yīng)用進(jìn)程如何保活?

    在Android應(yīng)用程序中,為了保證應(yīng)用的正常運(yùn)行和穩(wěn)定性,有時需要對應(yīng)用進(jìn)程進(jìn)行保活。以下是一些實現(xiàn)進(jìn)程?;畹姆椒ǎ?/div>
    的頭像 發(fā)表于 10-15 17:05 ?1047次閱讀
    【軟件干貨】Android應(yīng)用<b class='flag-5'>進(jìn)程</b>如何?;??

    rk3588s 怎么將gpio中斷綁定其它cpu

    目前了解只有GIC的中斷才能用這種:echo 2 > /proc/irq/102/smp_affinity, 方式綁定cpu,而GPIO這種是用不了這種方式綁定的。 想問下有其
    發(fā)表于 07-16 15:09

    如何正確配置華納云服務(wù)器以實現(xiàn)域名綁定?

    配置服務(wù)器以綁定域名通常涉及將域名解析服務(wù)器的IP地址,并在服務(wù)器設(shè)置相應(yīng)的虛擬主機(jī)或配置文件。這確保了當(dāng)用戶輸入特定域名時,他們會被導(dǎo)向正確的服務(wù)器和網(wǎng)站內(nèi)容。
    的頭像 發(fā)表于 07-15 16:16 ?515次閱讀

    esp8266怎樣才能正確的更新的代碼升級target?

    請問下: user1.bin、user2.bin它們編譯后分別鏈接哪些文件生成呢?怎樣才能正確的更新的代碼升級target? 以下是Esp8266燒錄和運(yùn)行信息: update
    發(fā)表于 07-12 11:50

    nginx重啟命令linux步驟是什么?

    worker進(jìn)程,不可能處理其它進(jìn)程的請求。   worker進(jìn)程的個數(shù)是可以設(shè)置的,一般我們會設(shè)置與機(jī)器cpu核數(shù)一致。同時,nginx為了更好的利用多核特性,具有
    發(fā)表于 07-11 17:13

    nginx重啟命令linux步驟是什么?

    worker進(jìn)程,不可能處理其它進(jìn)程的請求。   worker進(jìn)程的個數(shù)是可以設(shè)置的,一般我們會設(shè)置與機(jī)器cpu核數(shù)一致。同時,nginx為了更好的利用多核特性,具有
    發(fā)表于 07-10 16:40

    ESP32S3的差分OTA升級,有沒有方法可以用戶固定某個位置,或者用戶程序放到最后?

    我想做一個ESP32 S3 的差分OTA升級,但發(fā)現(xiàn)ESP-IDF編譯生成的BIN文件用戶程序放在前面,ESP32的庫文件放在后面。這樣即使改動很小的做出的差分程序也很大。有沒有方法可以用戶固定
    發(fā)表于 06-07 07:18
    主站蜘蛛池模板: 国产精品国产三级在线高清观看 | 激情婷婷网 | 饥渴少妇videos | 手机看片91 | 1024手机在线看永久免费 | 亚洲精品一线二线三线 | 亚洲综合激情另类专区 | 大尺度视频在线 | 男人日女人视频在线观看 | 午夜视频在线观看免费高清 | 天天成人综合网 | 高颜值美女啪啪 | 欧美在线bdsm调教一区 | a级黑粗大硬长爽猛视频毛片 | 午夜在线视频免费观看 | 天天干天天玩天天操 | 亚洲综合一区二区 | 午夜逼逼 | tom影院亚洲国产一区二区 | 亚洲精品一线二线三线 | 亚洲精品美女久久久久网站 | 三级网站在线看 | 国产精品久久久久久久成人午夜 | 亚洲加勒比在线 | 美女黄页网站免费进入 | 三级网站免费看 | 免费在线视频播放 | 全免费一级毛片在线播放 | 孩交精品xxxx视频视频 | 狂捣猛撞侍卫攻双性王爷受 | 久久伊人男人的天堂网站 | 欲色影院 | 久久免费香蕉视频 | aaaa在线观看| 亚州视频一区 | 天天夜天天干 | 国产成人黄网址在线视频 | 亚洲久久草 | 一级毛片一片毛 | 久久香蕉国产视频 | 色妹子在线 |