linux complete函數,Linux驅動中completion接口淺析(wait_for_complete例子,很好)

completion是一種輕量級的機制,它容許一個線程告訴另外一個線程工做已經完成。能夠利用下面的宏靜態建立completion: ?????????????????????????DECLARE_COMPLETION(my_completion);? ???????linux

若是運行時建立completion,則必須采用如下方法動態建立和初始化: ?????????????????????????struct compltion my_completion; ????????????????????????? init_completion(&my_completion);redis

completion的相關定義包含在kernel/include/Linux/completion.h中:shell

struct completion { ???????????????????????????????????? unsigned int done; ???????????????????????????????????? wait_queue_head_t wait; ???????????????????????? };app

#define COMPLETION_INITIALIZER(work) / ?????????????????????????????????????????????????????????? { 0, __WAIT_QUEUE_HEAD_INITIALIZER((work).wait) }less

#define DECLARE_COMPLETION(work) / ????????????????????????????????????????????????????? struct completion work = COMPLETION_INITIALIZER(work)測試

static inline void init_completion(struct completion *x) { ????????? x->done = 0; ????????? init_waitqueue_head(&x->wait); }ui

要等待completion,可進行以下調用: ??????????????????? void wait_for_completion(struct completion *c);this

觸發completion事件,調用: ?????????????????? void complete(struct completion *c);??? //喚醒一個等待線程 ?????????????????? void complete_all(struct completion *c);//喚醒全部的等待線程線程

為說明completion的使用方法,將《Linux設備驅動程序》一書中的complete模塊的代碼摘抄以下: /* * complete.c -- the writers awake the readers * * Copyright (C) 2003 Alessandro Rubini and Jonathan Corbet * Copyright (C) 2003 O'Reilly & Associates * * The source code in this file can be freely used, adapted, * and redistributed in source or binary form, so long as an * acknowledgment appears in derived source files.??? The citation * should list that the code comes from the book "Linux Device * Drivers" by Alessandro Rubini and Jonathan Corbet, published * by O'Reilly & Associates.???? No warranty is attached; * we cannot take responsibility for errors or fitness for use. * * $Id: complete.c,v 1.2 2004/09/26 07:02:43 gregkh Exp $ */日志

#include #include

#include ???/* current and everything */ #include ?/* printk() */ #include ??????/* everything... */ #include ???/* size_t */ #include

MODULE_LICENSE("Dual BSD/GPL");

static int complete_major = 253;//指定主設備號

DECLARE_COMPLETION(comp);

ssize_t complete_read (struct file *filp, char __user *buf, size_t count, loff_t *pos) { ???????? printk(KERN_DEBUG "process %i (%s) going to sleep/n", ???????? current->pid, current->comm); ???????? wait_for_completion(&comp); ???????? printk(KERN_DEBUG "awoken %i (%s)/n", current->pid, current->comm); ???????? return 0; /* EOF */ }

ssize_t complete_write (struct file *filp, const char __user *buf, size_t count, ??? loff_t *pos) { ???????? printk(KERN_DEBUG "process %i (%s) awakening the readers.../n", ???????? current->pid, current->comm); ???????? complete(&comp); ???????? return count;?/* succeed, to avoid retrial */ }

struct file_operations complete_fops = { ???????? .owner = THIS_MODULE, ???????? .read =??? complete_read, ???????? .write = complete_write, };

int complete_init(void) { ???????? int result;

/* ??? * Register your major, and accept a dynamic number ??? */ ??????? result = register_chrdev(complete_major, "complete", &complete_fops); ??????? if (result < 0) ??????????????? return result; ??????? if (complete_major == 0) ??????????????? complete_major = result;?/* dynamic */ ??????? return 0; }

void complete_cleanup(void) { ???????? unregister_chrdev(complete_major, "complete"); }

module_init(complete_init); module_exit(complete_cleanup);

該模塊定義了一個簡單的completion設備:任何試圖從該設備中讀取的進程都將等待,直到其余設備寫入該設備為止。編譯此模塊的Makefile以下: obj-m := complete.o KDIR := /lib/modules/$(Shell uname -r)/build PWD := $(shell pwd) default: $(MAKE) -C $(KDIR) M=$(PWD) modules clean: rm -f *.ko *.o *.mod.c

在linux終端中執行如下命令,編譯生成模塊,并進行動態加載。 #make #mknod completion c 253 0 #insmod complete.ko 再打開三個終端,一個用于讀進程: #cat completion 一個用于寫進程: #echo >completion 另外一個查看系統日志: #tail -f /var/log/messages

值得注意的是,當咱們使用的complete_all接口時,若是要重復使用一個completion結構,則必須執行 INIT_COMPLETION(struct completion c)來從新初始化它。能夠在kernel/include/linux/completion.h中找到這個宏的定義: ????????? #define INIT_COMPLETION(x) ((x).done = 0)

如下代碼對書中原有的代碼進行了一番變更,將喚醒接口由原來的complete換成了complete_all,而且為了重復利用completion結構,全部讀進程都結束后就從新初始化completion結構,具體代碼以下: #include #include

#include #include #include #include #include

MODULE_LICENSE("Dual BSD/GPL");

#undef KERN_DEBUG #define KERN_DEBUG "<1>"

static int complete_major=253; static int reader_count = 0;

DECLARE_COMPLETION(comp);

ssize_t complete_read (struct file *filp,char __user *buf,size_t count,loff_t *pos) { ?????????? printk(KERN_DEBUG "process %i (%s) going to sleep,waiting for writer/n",current->pid,current->comm); ?????????? reader_count++; ?????????? printk(KERN_DEBUG "In read ,before comletion: reader count = %d /n",reader_count); ?????????? wait_for_completion(&comp); ?????????? reader_count--; ?????????? printk(KERN_DEBUG "awoken %s (%i) /n",current->comm,current->pid); ?????????? printk(KERN_DEBUG "In read,after completion : reader count = %d /n",reader_count);

/*若是使用complete_all,則completion結構只能用一次,再次使用它時必須調用此宏進行從新初始化*/ ?????????? if(reader_count == 0) ?????????????????????? INIT_COMPLETION(comp);

return 0; }

ssize_t complete_write(struct file *filp,const char __user *buf,size_t count,loff_t *pos) { ?????????? printk(KERN_DEBUG "process %i (%s) awoking the readers.../n",current->pid,current->comm); ?????????? printk(KERN_DEBUG "In write ,before do complete_all : reader count = %d /n",reader_count);

if(reader_count != 0)?? ?????????????????? complete_all(&comp);

printk(KERN_DEBUG "In write ,after do complete_all : reader count = %d /n",reader_count);

return count; }

struct file_operations complete_fops={ ?????????? .owner = THIS_MODULE, ?????????? .read = complete_read, ?????????? .write = complete_write, };

int complete_init(void) { ?????????? int result;

result=register_chrdev(complete_major,"complete",&complete_fops); ?????????? if(result<0) ??????????????????? return result; ?????????? if(complete_major==0) ?????????????????? complete_major =result;

printk(KERN_DEBUG??? "complete driver test init! complete_major=%d/n",complete_major); ?????????? printk(KERN_DEBUG "靜態初始化completion/n");

return 0; }

void complete_exit(void) { ?????????? unregister_chrdev(complete_major,"complete"); ?????????? printk(KERN_DEBUG??? "complete driver??? is removed/n"); }

module_init(complete_init); module_exit(complete_exit);

這里測試步驟和上述同樣,只不過須要多打開幾個終端來執行多個進程同時讀操做。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/394807.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/394807.shtml
英文地址,請注明出處:http://en.pswp.cn/news/394807.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

vue.js 全局應用js_如何在不到7分鐘的時間內測試您的Vue.js應用

vue.js 全局應用jsby Mukul Khanna由Mukul Khanna 如何在不到7分鐘的時間內測試您的Vue.js應用 (How you can test your Vue.js apps in less than seven minutes) Before we dive into the implementation, let’s get a few concepts cleared.在深入研究實現之前&#xff0c…

MongoDB在Linux下常用優化設置

MongoDB在Linux下常用優化設置以下是一些MongoDB推薦的常用優化設置。在生產環境下選取合適的參數值&#xff0c;例如預讀值和默認文件描述符數目等&#xff0c;會對系統性能有很大的影響。1、關閉數據庫文件的 atime禁止系統對文件的訪問時間更新會有效提高文件讀取的性能。這…

iOS常用第三方庫大全,史上最全第三方庫收集

下拉刷新 EGOTableViewPullRefresh – 最早的下拉刷新控件。SVPullToRefresh – 下拉刷新控件。MJRefresh – 僅需一行代碼就可以為UITableView或者CollectionView加上下拉刷新或者上拉刷新功能。可以自定義上下拉刷新的文字說明。具體使用看“使用方法”。 &#xff08;國人寫…

ipconfig沒有顯示ip_TCP/IP 協議修復網絡問題

nternet 在 TCP/IP 協議上工作&#xff0c;如果 TCP/IP 協議堆棧在 Windows 或任何其他操作系統(例如 Linux 或 MacOS)中無法正常工作&#xff0c;則您的 Internet 連接會出現問題。解決 Internet 問題的最佳方法是重置 TCP/IP 堆棧設置。如何在 Windows 中重置 TCP/IP 堆棧&am…

mysql卸載

先執行mysql安裝程序&#xff0c;點擊移除&#xff0c;然后再刪除對應的安裝路徑&#xff0c;必要的時候還要刪除注冊表信息。轉載于:https://www.cnblogs.com/772933011qq/p/6007752.html

mysql-linux64,Linux64下mysql安裝和開辟

1.1地址&#xff1a;http://www.mysql.com/downloads/mysql/5.5.html&#xff03;downloads版本&#xff1a;5.1.68平臺&#xff1a;linux generalGeneric Linux (glibc 2.3) (x86&#xff0c; 64-bit)&#xff0c; RPM Package版本&#xff1a;MySQL Server(MySQL-server-5.1.…

mysql 內置功能 存儲過程 目錄

mysql 內置功能 存儲過程介紹mysql 內置功能 存儲過程 創建無參存儲過程mysql 內置功能 存儲過程 創建有參存儲過程mysql 內置功能 存儲過程 刪除存儲過程轉載于:https://www.cnblogs.com/mingerlcm/p/10533021.html

簡化C語言文法

程序 → 外部聲明|程序 外部聲明 外部聲明 → 定義函數|定義 函數定義 → 類型標識符 聲明部分語句 類型標識符 → 空類型|字符型|整型|浮點型 聲明部分語句 → 指針 直接聲明|直接聲明 指針 → * |* 指針 直接聲明 → 標識符 | 直接聲明[ ] | 直接聲明[常數表達式] | 標識符&a…

elixir 規格_Elixir:一種高畫質的編程語言

elixir 規格by CityBase按CityBase Elixir&#xff1a;一種高畫質的編程語言 (Elixir: A Big-Picture Programming Language) Elixir使程序員的工作更好&#xff0c;并且使他們的工作更好 (Elixir makes programmers better at their work, and it makes their work better) A…

python截圖識別文字_用百度ocr+微信截圖實現文字識別

作用&#xff1a;將圖片中的文字識別出來 一、調用微信截圖dll控件 將微信截圖插件復制到項目文件&#xff0c;使用ctypes加載&#xff08;膠水語言就是給力&#xff09; def capture(): try: dll ctypes.cdll.LoadLibrary(PrScrn.dll) except Exception: print("Dll loa…

MySQL啟動很慢的原因

我們在啟動MySQL的時候&#xff0c;常常會遇到的是&#xff0c; 當執行啟動命令后&#xff0c;它會"Start MySQL ....." 一直不停的執行&#xff0c;也不中斷&#xff0c;也不成功 這里會出現此現象的原因有以下三條&#xff1a; 1. 配置文件中的InnoDBuffer數大于物…

linux線程出錯,在線程應用程序(linux,pthreads)中讀取文件大小時出錯

我試圖從Linux中的文件夾中讀取所有文件和目錄&#xff0c;其線程為 獲取最大文件大小&當前目錄和當前目錄樹下的名稱。在線程應用程序(linux&#xff0c;pthreads)中讀取文件大小時出錯主線程掃描基本目錄查找文件&#xff0c;當找到它的目錄時&#xff0c;會生成一個新線…

【用jQuery來判斷瀏覽器的類型】及【javascript獲取用戶ip地址】

用jQuery來判斷瀏覽器的類型,主要是使用$.browser這個工具類,使用方法: $.browser.[瀏覽器關鍵字] //谷歌瀏覽器、360瀏覽器等其他一些瀏覽器&#xff0c;沒有專門的判斷 function appInfo() {var bro $.browser;var binfo "";if (bro.msie) {binfo "Micr…

python函數學習1

函數1 &#xff08;1&#xff09;定義&#xff1a; def 函數名&#xff08;參數列表&#xff09;函數體 &#xff08;2&#xff09;參數傳遞&#xff1a; 在python中&#xff0c;一切都是對象&#xff0c;類型也屬于對象&#xff0c;變量是沒有類型的。 a [1,2,3] a "he…

kafka應用于區塊鏈_Apache Kafka的區塊鏈實驗

kafka應用于區塊鏈by Luc Russell盧克羅素(Luc Russell) Apache Kafka的區塊鏈實驗 (A blockchain experiment with Apache Kafka) Blockchain technology and Apache Kafka share characteristics which suggest a natural affinity. For instance, both share the concept o…

pythonfor循環100次_以寫代學: python for循環 range函數 xrange函數

腳本一&#xff1a; #!/usr/bin/env python # coding: utf8 sum100 0 for i in range(101): sum100 i #&#xff08;1&#xff09;range是一個可以取值的函數&#xff0c;上邊這個取的是0-100&#xff0c;并不包含101 #&#xff08;2&#xff09;也可以指定&#xff0c;比如r…

iis下php 500錯誤

很不想用iis&#xff0c;然而客戶不想增加機器&#xff0c;只好按客戶的意思了。可是沒想到發送短信以在本地 機器上是好的&#xff0c;在iis下直接500。 ??一開始以為是防火墻問題&#xff0c;后來檢查了一下沒有&#xff0c;再后來換了一個短信接口&#xff0c;就莫名其妙好…

linux mv 遞歸拷貝,奇技淫巧 - 給Linux中的cp和mv命令中添加進度條的高級拷貝

GNU cp和GNU mv命令用于在GNU/Linux操作系統中復制和移動文件和目錄。這兩個命令缺少的一個特性是它們不顯示任何進度條。如果復制一個大文件或目錄&#xff0c;您就不知道完成復制過程需要多長時間&#xff0c;也不知道復制的數據所占的百分比。還有您將看不到當前正在復制哪個…

webgl 著色器_如何在WebAssembly中使用WebGL著色器

webgl 著色器by Dan Ruta通過Dan Ruta 在WebAssembly中使用WebGL著色器 (Using WebGL shaders in WebAssembly) WebAssembly is blazing fast for number crunching, game engines, and many other things, but nothing can quite compare to the extreme parallelization of …

【洛谷P1966】火柴排隊

兩列排序后將編號一一對應 歸并排序求逆序對 &#xff08;每一次交換就去掉一個逆序對&#xff09; 1 #include<cstdio>2 #include<cstring>3 #include<algorithm>4 #define ll long long5 using namespace std;6 const int N100100;7 const ll P99999997;8 …