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

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

RK3568驅動指南|第三篇-并發與競爭-第19章 并發與競爭實驗

北京迅為電子 ? 2025-02-24 16:26 ? 次閱讀

瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工藝,搭載一顆四核Cortex-A55處理器和Mali G52 2EE圖形處理器。RK3568支持4K解碼和1080P編碼,支持SATA/PCIE/USB3.0外圍接口。RK3568內置獨立NPU,可用于輕量級人工智能應用。RK3568支持安卓11和linux系統,主要面向物聯網網關、NVR存儲、工控平板、工業檢測、工控盒、卡拉OK、云終端、車載中控等行業。

?

wKgZPGe8LQ6ASKzbAAjhsFOvqKY735.png

迅為RK568郵票孔版開發板:
還在為工控機性能不足而煩惱?
還在為開發周期長而焦慮?
迅為RK568郵票孔版開發板,為您提供一站式解決方案!

強勁性能,賦能工業未來:
搭載瑞芯微RK568高性能處理器,采用先進制程工藝,提供澎湃算力,輕松應對復雜工業場景。
支持多種操作系統,如Android、Linux等,滿足不同應用需求。
豐富接口,擴展性強,可連接多種工業設備,構建穩定可靠的工業控制系統。

郵票孔設計,靈活易用:
采用郵票孔連接方式,方便快捷,節省空間,易于集成到各種工控設備中。
提供配套外殼,防護等級高,適應各種惡劣工業環境。
提供完善的技術支持和開發資料,助您快速上手,縮短開發周期。

廣泛應用于工業自動化控制、機器視覺智能網關、工業機器人、物聯網終端等。

wKgZPGe8LQ6AJ2VnAAIvCcsa3kc409.png

【公眾號】迅為電子

第19章 并發與競爭實驗

在前面章節的學習中,相信大家已經對用戶空間與內核空間數據傳遞進行了實驗,假如要傳遞的數據被存放在了全局變量,該數據就可以作為共享資源被多個任務共同讀寫,從而造成數據的錯誤傳輸,多個程序同時訪問一個共享資源產生的問題就叫做競爭。競爭產生的根本原因就是Linux系統的并發訪問。

在本章節中首先會對并發與并行的概念進行講解,隨后對競爭產生的原因進行總結,最后以一個實際的競爭實驗加深大家的理解。下面就讓我們開始本章節的學習吧。

19.1并發與競爭

19.1.1并發

早期計算機大多只有一個CPU核心,一個CPU在同一時間只能執行一個任務,當系統中有多個任務等待執行時,CPU只能執行完一個再執行下一個。而計算機的很多指令會涉及I/O操作,執行速度遠遠低于CPU內高速存儲器的存取速度,這就導致CPU經常處于空閑狀態,只能等待I/O操作完成后才能繼續執行后面的指令。為了提高CPU利用率,減少等待時間,提出了CPU并發工作理論。

所謂并發,就是通過算法將CPU資源合理地分配給多個任務,當一個任務執行I/O操作時,CPU可以轉而執行其它的任務,等到I/O操作完成以后,或者新的任務遇到I/O操作時,CPU再回到原來的任務繼續執行。

下圖(圖19-1)展示了兩個任務并發執行的過程(為了容易理解,這里以兩個任務并發執行為例,當然一個CPU核心并不僅僅只能兩個任務并發):

wKgZPGe8LQ2ATpY8AAEBBQfSMt4318.png

雖然CPU在同一時刻只能執行一個任務,但是通過將CPU的使用權在恰當的時機分配給不同的任務,使得多個任務看起來是一起執行的(CPU的執行速度極快,多任務切換的時間也極短)。

至此關于并發的概念就講解完成了。

19.1.2并行

并發是針對單核CPU提出的,而并行則是針對多核CPU提出的。和單核CPU不同,多核CPU真正實現了“同時執行多個任務”。多核CPU的每個核心都可以獨立地執行一個任務,而且多個核心之間不會相互干擾。在不同核心上執行的多個任務,是真正地同時運行,這種狀態就叫做并行。雙核CPU的工作狀態如下圖(圖19-2)所示:

wKgZO2e8LQ2ANcaDAAG12uC-O9o637.png

雙核CPU執行兩個任務時,每個核心各自執行一個任務,和單核CPU在兩個任務之間不斷切換相比,它的執行效率更高。

至此對于并行的概念就講解完成了。

19.1.3并發+并行

在并行的工作狀態中,兩個CPU分別執行兩個任務,是一種理想狀態。但是在實際場景中,處于運行狀態的任務是非常多的,以實際辦公電腦為例,windows系統在開機之后會運行幾十個任務,而CPU往往只有4核、8核等,遠遠低于任務的數量,這個時候就會同時存在并發和并行兩種情況,即所有核心在并行工作的同時,每個核心還要并發工作。

例如一個雙核 CPU要執行四個任務,它的工作狀態如下圖(圖19-3)所示:

wKgZPGe8LQ2AJxzpAAGU7E7MGq4039.png

為了容易理解,這里是以兩個任務并發執行為例,當然一個CPU核心并不僅僅只能兩個任務并發,并發任務的數量和操作系統的分配方式、以及每個任務的工作狀態有關系。

至此,對于并發+并行的概念講解就結束了。

并發可以看作是并行的理想狀態,為了便于講解和避免產生歧義,之后的章節無論是并發還是并行,都會統稱為并發。

19.1.4競爭

并發可能會造成多個程序同時訪問一個共享資源,這時候由并發同時訪問一個共享資源產生的問題就叫做競爭。

競爭產生的原因如下所示:

(1)多線程的并發訪問。由于Linux是多任務操作系統,所以多線程訪問是競爭產生的基本原因。

(2)中斷程序的并發訪問。中斷任務產生后,CPU會立刻停止當前工作,從而去執行中斷中的任務,如果中斷任務對共享資源進行了修改,就會產生競爭。

(3)搶占式并發訪問。linux2.6及更高版本引入了搶占式內核,高優先級的任務可以打斷低優先級的任務。在線程訪問共享資源的時候,另一個線程打斷了現在正在訪問共享資源的線程同時也對共享資源進行操作,從而造成了競爭。

(4)多處理器(SMP)并發訪問。多核處理器之間存在核間并發訪問。

19.1.5共享資源的保護

競爭是由并發訪問同一個共享資源產生的。為了防止“競爭”的產生就要對共享資源進行保護,這里提到的共享資源又是什么呢?

以實際生活中的共享資源為例,可以是公共電話,也可以是共享單車、共享充電寶等公共物品,以上都屬于共享資源的范疇,以公共電話為例,每個人都可以對它進行使用,但在同一時間內只能由一個人進行使用,如果兩個人都要對電話進行使用,則產生了競爭。而在實際的驅動的代碼中,共享資源可以是全局變量,也可以是驅動中的設備結構體等,需要根據具體的驅動程序來進行分析。在下一小節的實驗中,會以全局變量為例,進行并發與競爭實驗。

19.2實驗程序的編寫

19.2.1驅動程序編寫

本實驗對應的網盤路徑為:iTOP-RK3568開發板【底板V1.7版本】\03_【iTOP-RK3568開發板】指南教程\02_Linux驅動配套資料\04_Linux驅動例程\14\module。

本實驗將編寫并發與競爭的驅動代碼,首先完善字符設備驅動框架,然后通過copy_from_user(…)函數接收用戶空間傳遞到內核空間的數據并進行判斷,如果接收到的字符串數據為“topeet”會在睡眠4秒鐘后打印接收到的數據,如果接收到的字符串數據為“itop”會在睡眠2秒鐘后打印接收到的數據。

編寫完成的example.c代碼如下所示

#include

#include

#include

#include

#include

#include

#include

static int open_test(struct inode *inode,struct file *file)

{

printk("\nthis is open_test \n");

return 0;

}

static ssize_t read_test(struct file *file,char __user *ubuf,size_t len,loff_t *off)

{

int ret;

char kbuf[10] = "topeet";//定義char類型字符串變量kbuf

printk("\nthis is read_test \n");

ret = copy_to_user(ubuf,kbuf,strlen(kbuf));//使用copy_to_user接收用戶空間傳遞的數據

if (ret != 0){

printk("copy_to_user is error \n");

}

printk("copy_to_user is ok \n");

return 0;

}

static char kbuf[10] = {0};//定義char類型字符串全局變量kbuf

static ssize_t write_test(struct file *file,const char __user *ubuf,size_t len,loff_t *off)

{

int ret;

ret = copy_from_user(kbuf,ubuf,len);//使用copy_from_user接收用戶空間傳遞的數據

if (ret != 0){

printk("copy_from_user is error\n");

}

if(strcmp(kbuf,"topeet") == 0 ){//如果傳遞的kbuf是topeet就睡眠四秒鐘

ssleep(4);

}

else if(strcmp(kbuf,"itop") == 0){//如果傳遞的kbuf是itop就睡眠兩秒鐘

ssleep(2);

}

printk("copy_from_user buf is %s \n",kbuf);

return 0;

}

static int release_test(struct inode *inode,struct file *file)

{

//printk("\nthis is release_test \n");

return 0;

}

struct chrdev_test {

dev_t dev_num;//定義dev_t類型變量dev_num來表示設備號

int major,minor;//定義int類型的主設備號major和次設備號minor

struct cdev cdev_test;//定義struct cdev類型結構體變量cdev_test,表示要注冊的字符設備

struct class *class_test;//定于struct class *類型結構體變量class_test,表示要創建的類

};

struct chrdev_test dev1;//創建chrdev_test類型的

struct file_operations fops_test = {

.owner = THIS_MODULE,//將owner字段指向本模塊,可以避免在模塊的操作正在被使用時卸載該模塊

.open = open_test,//將open字段指向open_test(...)函數

.read = read_test,//將read字段指向read_test(...)函數

.write = write_test,//將write字段指向write_test(...)函數

.release = release_test,//將release字段指向release_test(...)函數

};

static int __init atomic_init(void)

{

if(alloc_chrdev_region(&dev1.dev_num,0,1,"chrdev_name") < 0 ){//自動獲取設備號,設備名chrdev_name

printk("alloc_chrdev_region is error \n");

}

printk("alloc_chrdev_region is ok \n");

dev1.major = MAJOR(dev1.dev_num);//使用MAJOR()函數獲取主設備號

dev1.minor = MINOR(dev1.dev_num);//使用MINOR()函數獲取次設備號

printk("major is %d,minor is %d\n",dev1.major,dev1.minor);

cdev_init(&dev1.cdev_test,&fops_test);//使用cdev_init()函數初始化cdev_test結構體,并鏈接到fops_test結構體

dev1.cdev_test.owner = THIS_MODULE;//將owner字段指向本模塊,可以避免在模塊的操作正在被使用時卸載該模塊

cdev_add(&dev1.cdev_test,dev1.dev_num,1);//使用cdev_add()函數進行字符設備的添加

dev1.class_test = class_create(THIS_MODULE,"class_test");//使用class_create進行類的創建,類名稱為class_test

device_create(dev1.class_test,0,dev1.dev_num,0,"device_test");//使用device_create進行設備的創建,設備名稱為device_test

return 0;

}

static void __exit atomic_exit(void)

{

device_destroy(dev1.class_test,dev1.dev_num);//刪除創建的設備

class_destroy(dev1.class_test);//刪除創建的類

cdev_del(&dev1.cdev_test);//刪除添加的字符設備cdev_test

unregister_chrdev_region(dev1.dev_num,1);//釋放字符設備所申請的設備號

printk("module exit \n");

}

module_init(atomic_init);

module_exit(atomic_exit)

MODULE_LICENSE("GPL v2");

MODULE_AUTHOR("topeet");

對于重要邏輯部分已經加粗,后續章節的實驗都是對上述并發與競爭實驗的改進,以不同的方式來避免競爭的產生。

19.2.2編寫測試APP

本實驗應用程序對應的網盤路徑為:iTOP-RK3568開發板【底板V1.7版本】\03_【iTOP-RK3568開發板】指南教程\02_Linux驅動配套資料\04_Linux驅動例程\14\app。

本測試app較為簡單,需要輸入兩個參數,第一個參數為對應的設備節點,第二個參數為“topeet”或者“itop”,分別代表向設備寫入的數據,編寫完成的應用程序app.c內容如下所示:

#include

#include

#include

#include

#include

#include

int main(int argc, char *argv[])

{

int fd;//定義int類型的文件描述符

char str1[10] = {0};//定義讀取緩沖區str1

fd = open(argv[1],O_RDWR);//調用open函數,打開輸入的第一個參數文件,權限為可讀可寫

if(fd < 0 ){

printf("file open failed \n");

return -1;

}

/*如果第二個參數為topeet,條件成立,調用write函數,寫入topeet*/

if (strcmp(argv[2],"topeet") == 0 ){

write(fd,"topeet",10);

}

/*如果第二個參數為itop,條件成立,調用write函數,寫入itop*/

else if (strcmp(argv[2],"itop") == 0 ){

write(fd,"itop",10);

}

close(fd);

return 0;

}

19.3運行測試

19.3.1編譯驅動程序

在上一小節中的example.c代碼同一目錄下創建Makefile文件,Makefile文件內容如下所示:

export ARCH=arm64#設置平臺架構

export CROSS_COMPILE=aarch64-linux-gnu-#交叉編譯器前綴

obj-m += example.o #此處要和你的驅動源文件同名

KDIR :=/home/topeet/Linux/linux_sdk/kernel #這里是你的內核目錄

PWD ?= $(shell pwd)

all:

make -C $(KDIR) M=$(PWD) modules #make操作

clean:

make -C $(KDIR) M=$(PWD) clean #make clean操作

對于Makefile的內容注釋已在上圖添加,保存退出之后,來到存放example.c和Makefile文件目錄下,如下圖所示:

wKgZPGe8LQuALbRIAACG4QnbV6M606.png

然后使用命令“make”進行驅動的編譯,編譯完成如下圖(圖19-5)所示:

wKgZO2e8LQ6AZwabAAKEHCIrLuY942.png

編譯完生成example.ko目標文件,如下圖(圖19-6)所示:

wKgZO2e8LQuASpHnAAD2ogIkBP0752.png

至此驅動模塊就編譯成功了,下面進行應用程序的編譯。

19.3.2編譯應用程序

來到應用程序app.c文件的存放路徑如下圖(圖19-7)所示:

wKgZPGe8LQuAa85QAABYfgBxKDc393.png

然后使用以下命令對app.c進行交叉編譯,編譯完成如下圖(圖19-8)所示:

1

aarch64-linux-gnu-gcc -o app app.c -static

wKgZO2e8LQuAOCGzAADBqYwoMio972.png

生成的app文件就是之后放在開發板上運行的可執行文件,至此應用程序的編譯就完成了。

19.3.3運行測試

開發板啟動之后,使用以下命令進行驅動模塊的加載,如下圖(圖19-9)所示:

1

insmod example.ko

wKgZO2e8LQuAXHpIAADMVfqOgBE144.png

可以看到申請的主設備號和次設備號就被打印了出來,然后使用以下代碼對自動生成的設備節點device_test進行查看,如下圖(圖19-10)所示:

1

ls /dev/device_test

wKgZPGe8LQuANV-EAAB7UXUI4Ik807.png

可以看到device_test節點已經被自動創建了,然后使用以下命令運行測試app,運行結果如下圖(圖19-11)所示:

1

./app /dev/device_test topeet

wKgZO2e8LQ2ACcJEAAECoKTrPqg955.png

可以看到傳遞的buf值為topeet,然后輸入以下命令在后臺運行兩個app,來進行競爭測試,運行結果如下圖(圖19-12)所示:

./app /dev/device_test topeet &

./app /dev/device_test itop &

wKgZO2e8LQ2ALCJ9AAHzmWTROCM773.png

在不存在競爭的情況下,傳遞的兩個字符串數據應該是topeet和itop,而在上圖中的打印信息為兩個itop,原因是第二個app應用程序運行之后對共享資源進行了修改,兩個app應用程序就產生了競爭關系,會在之后的章節中使用不同的方法對上述驅動程序進行改進,從而避免競爭的產生。

最后可以使用以下命令進行驅動的卸載,如下圖(圖19-13)所示:

1

rmmod example.ko

wKgZPGe8LQ2Ab3_cAABvdcKT5jw156.png

至此,并發與競爭的實驗就完成了。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 驅動
    +關注

    關注

    12

    文章

    1878

    瀏覽量

    86321
  • 開發板
    +關注

    關注

    25

    文章

    5378

    瀏覽量

    100678
  • RK3568
    +關注

    關注

    5

    文章

    559

    瀏覽量

    5902
收藏 人收藏

    評論

    相關推薦

    迅為RK3568開發板驅動指南Linux中通用SPI設備驅動

    迅為RK3568開發板驅動指南Linux中通用SPI設備驅動
    的頭像 發表于 01-23 11:02 ?2329次閱讀
    迅為<b class='flag-5'>RK3568</b>開發板<b class='flag-5'>驅動</b><b class='flag-5'>指南</b>Linux中通用SPI設備<b class='flag-5'>驅動</b>

    文檔更新 |迅為 RK3568開發板驅動指南-第十五/十六

    ? 第三篇 并發競爭 19 并發
    發表于 07-08 11:04

    文檔更新 | 迅為RK3568驅動指南-第十七篇(串口)

    實驗 14 內核空間與用戶空間數據交互實驗 15 文件私有數據
    發表于 09-24 10:42

    迅為iTOP-RK3568開發板驅動開發指南-第十八 PWM

    17 Linux錯誤處理實驗 18 點亮LED燈實驗 ? 第三篇
    發表于 10-29 10:13

    rk3568硬件開發筆記(第三篇 ) 網絡設計

    rk3568硬件開發筆記(第三篇 ) 網絡設計 第一節:WIFI電路設計 WiFi設計說明1、WiFi型號ITM1723-DS,此模塊需要外部預留26MHZ晶振;注意C6201C6204這2個匹配
    發表于 03-05 10:52

    iTOP-RK3568開發板驅動指南第五-中斷

    _字符設備基礎 第三期_并發競爭 第四期_高級字符設備進階 第五期_中斷 第六期_平臺總線 第七期_設備樹 第八期_設備樹插件 第九期_設備模型 第十期_熱插拔 第十一期_pinctrl子系統 未完待續,持續更新中...嗶哩嗶
    發表于 09-04 10:53

    更新 | 持續開源 迅為RK3568驅動指南第十一篇-pinctrl子系統

    熱插拔 11 pinctrl子系統 未完待續,持續更新中... 視頻教程更新至十二期 第一期_驅動基礎 第二期_字符設備基礎 第三
    發表于 10-18 11:12

    《Linux設備驅動開發詳解》7、Linux設備驅動中的并發控制

    《Linux設備驅動開發詳解》7、Linux設備驅動中的并發控制
    發表于 10-27 11:37 ?10次下載
    《Linux設備<b class='flag-5'>驅動</b>開發詳解》<b class='flag-5'>第</b>7<b class='flag-5'>章</b>、Linux設備<b class='flag-5'>驅動</b>中的<b class='flag-5'>并發</b>控制

    i.MX6ULL|并發競爭實驗

    常用的處理并發競爭的機制有四種,原子操作、自旋鎖、信號量和互斥體。下邊就通過編寫驅動來實現,展示一下相關效果。當前臺的應用一直運行,控制臺是不能輸入指令,測試并發
    的頭像 發表于 08-02 15:40 ?596次閱讀
    i.MX6ULL|<b class='flag-5'>并發</b>與<b class='flag-5'>競爭</b><b class='flag-5'>實驗</b>

    RK3568驅動指南驅動基礎進階-進階8 內核運行ko文件總結

    RK3568驅動指南驅動基礎進階-進階8 內核運行ko文件總結
    的頭像 發表于 01-31 14:58 ?1420次閱讀
    <b class='flag-5'>RK3568</b><b class='flag-5'>驅動</b><b class='flag-5'>指南</b>|<b class='flag-5'>驅動</b>基礎進階<b class='flag-5'>篇</b>-進階8 內核運行ko文件總結

    RK3568驅動指南驅動基礎進階-進階5 自定義實現insmod命令實驗

    RK3568驅動指南驅動基礎進階-進階5 自定義實現insmod命令實驗
    的頭像 發表于 02-20 14:10 ?963次閱讀
    <b class='flag-5'>RK3568</b><b class='flag-5'>驅動</b><b class='flag-5'>指南</b>|<b class='flag-5'>驅動</b>基礎進階<b class='flag-5'>篇</b>-進階5 自定義實現insmod命令<b class='flag-5'>實驗</b>

    迅為RK3568開發板驅動開發指南-輸入子系統

    迅為RK3568開發板驅動開發指南-輸入子系統
    的頭像 發表于 02-23 15:11 ?1358次閱讀
    迅為<b class='flag-5'>RK3568</b>開發板<b class='flag-5'>驅動</b>開發<b class='flag-5'>指南</b>-輸入子系統

    瑞芯微RK3568 USB驅動

    瑞芯微RK3568 USB驅動程序
    發表于 11-11 14:18 ?3次下載

    技術分享 | RK3568編譯第三驅動

    這里就以我司IAC-RK3568-Kit開發板為例,分享如何在當前內核下編譯第三驅動模塊。我們需要向模塊供應商拿到一份適配Linux的驅動源碼,這里主要是要向供應
    的頭像 發表于 03-06 17:25 ?441次閱讀
    技術分享 | <b class='flag-5'>RK3568</b>編譯<b class='flag-5'>第三</b>方<b class='flag-5'>驅動</b>

    【北京迅為】iTOP-RK3568開發板OpenHarmony系統南向驅動開發-4 UART基礎知識

    【北京迅為】iTOP-RK3568開發板OpenHarmony系統南向驅動開發-4 UART基礎知識
    的頭像 發表于 03-17 15:50 ?304次閱讀
    【北京迅為】iTOP-<b class='flag-5'>RK3568</b>開發板OpenHarmony系統南向<b class='flag-5'>驅動</b>開發-<b class='flag-5'>第</b>4<b class='flag-5'>章</b> UART基礎知識
    主站蜘蛛池模板: 深夜视频在线观看免费 | 色视频在线观看网站 | 日本天天操 | 国产午夜精品久久久久免费视小说 | 国产三级精品最新在线 | 婷婷影院在线综合免费视频 | www一区二区三区 | 婷婷六月激情在线综合激情 | 99久久久免费精品免费 | 日本大片免费播放网站 | 天天舔天天射 | 自拍偷自拍亚洲精品被多人伦好爽 | 亚洲成在人天堂一区二区 | 国产小视频在线观看www | 四虎影院中文字幕 | 黄页网站在线 | 欧美性色欧美a在线观看 | 欧美一区二区影院 | 中国一级毛片aaa片 中国一级特黄aa毛片大片 | 九色在线| 窝窝视频成人影院午夜在线 | 国产婷婷色一区二区三区 | 夜夜春宵翁熄性放纵古代 | 欧美性另类| 欧美一级免费片 | 香蕉久久影院 | 午夜免费啪啪 | 色多多视频在线播放 | 男男gay污小黄文 | 午夜精品免费 | 成人黄网大全在线观看 | 午夜想想爱午夜剧场 | 婷婷香蕉 | 午夜在线免费观看 | 成人欧美一区二区三区视频不卡 | www四虎在线高清 | 天堂一区二区三区在线观看 | 九色九色九色在线综合888 | 色噜噜狠狠色综合欧洲selulu | 大黄蕉 | 国产性videostv另类极品 |