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.mzph.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 …