linux设备驱动开发4.0_linux设备驱动开发详解 基于最新的linux4.0内核 - CSDN
  • Linux设备驱动开发详解:基于最新的Linux 4.0内核》

    《Linux设备驱动开发详解:基于最新的Linux 4.0内核》


    china-pub   天猫     dangdang   京东   


    China-pub 8月新书销售榜



    推荐序一

      技术日新月异,产业斗转星移,滚滚红尘,消逝的事物太多,新事物的诞生也更迅猛。众多新生事物如灿烂烟花,转瞬即逝。当我们仰望星空时,在浩如烟海的专业名词中寻找,赫然发现,Linux的生命力之旺盛顽强,斗志之昂扬雄壮,令人称奇。它正以摧枯拉朽之势迅速占领包括服务器、云计算、消费电子、工业控制、仪器仪表、导航娱乐等在内的众多应用领域,并逐步占据许多WINCE、VxWorks的传统嵌入式市场。

      Linux所及之处,所向披靡。这与Linux的社区式开发模式,迅速的迭代不无关系。Linux每2~3月更新一次版本,吸纳新的体系架构、芯片支持、驱动、内核优化和新特性,这使得Linux总是能够在第一时间内迎合用户的需求,快速地适应瞬息万变的市场。由Linux以及围绕着Linux进行产品研发的众多企业和爱好者构成了一个庞大的Linux生态圈。而本书,无疑给这个庞大的生态圈注入了养料。

      然而,养料的注入应该是持续不断的。至今,Linux内核的底层BSP、驱动框架和内核实现发生了许多变更,本书涵盖了这些新的变化,这将给予开发者更多新的帮助。内核的代码不断重构并最优化,而本书也无疑是一次重大的重构。

      生命不息,重构不止。

      周立功

      推荐序二

      在翻译了《Understanding the Linux Kernel》和《Linux Kernel Development》这两本书后,每当有读者询问如何学习Linux内核时,我都不敢贸然给出建议。如此庞大的内核,各个子系统之间的关系错综复杂,代码不断更新和迭代,到底该从何入手?你的出发点是哪里?你想去的彼岸又是哪里?相应的学习方法都不同。

      一旦踏入Linux内核领域,要精通Linux内核的精髓,几乎没有捷径可走。尽管通往山顶的路有无数条,但每条路上都布满荆棘,或许时间和毅力才是斩荆披棘的利器。

      从最初到现在,Linux内核的版本更新达上千个,代码规模不断增长,平均每个版本的新增代码有4万行左右。在源代码的10个主要子目录(arch、init、include、kernel、mm、IPC、fs、lib、net、drivers)中,驱动程序的代码量呈线性增长趋势。

      从软件工程角度来看内核代码的变化规律,Linux的体系结构相对稳定,子系统数变化不大,平均每个模块的复杂度呈下降趋势,但系统整体规模和复杂性分别呈超线性和接近线性增长趋势。drivers和arch等模块的快速变化是引起系统复杂性增加的主因。那么,在代码量最多的驱动程序中,有什么规律可循?最根本的又是什么?

      本书更多的是关于Linux内核代码背后机理的讲解,呈现给读者的是一种思考方法,让读者能够在思考中举一反三。尽管驱动程序只是内核的一个子系统,但Linux内核是一种整体结构,牵一发而动全局,对Linux内核其他相关知识的掌握是开发驱动的基础。本书的内容包括中断、定时器、进程生命周期、uevent、并发、编译乱序、执行乱序、等待队列、I/O模型、内存管理等,实例代码也被大幅重构。

      明代著名的思想家王明阳有句名言“知而不行,是为不知;行而不知,可以致知”。因此在研读本书时,你一定要亲身实践,在实践之后要提升思考,如此,你才可以越过代码本身而看到内核的深层机理。

      陈莉君

      西安邮电大学


    媒体评论

      十多年前,我在海外一家路由器公司从事底层软件开发时,一本《Linux Device Driver》(LDD)使我受益匪浅。近年来,我在从事基于ARM的嵌入式操作系统教学时发现,很多Linux设备驱动中的新技术,比如Device Tree、sysfs等,在LDD3中均没有涉及。而市面上的翻译书晦涩难懂,有的还不如英文原书好理解。宋宝华是我尊敬的技术人员,十年如一日,在Linux内核及设备驱动领域潜心耕耘,堪称大师。本书无论从汉语的遣词造句,案例的深入浅出,还是对前沿技术的掌握,对难点技术丝丝入扣的分析,都体现出了强烈的“工匠精神”,堪称经典,值得推荐。
      ——Xilinx前大中华区大学计划经理、慕客信CEO  谢凯年


      设备驱动程序是连接计算机软件和硬件的纽带和桥梁,开发者在嵌入式操作系统的开发移植过程中,有将近70%~80%的精力都用在了驱动程序的开发与调试方面。这就对设备驱动程序开发人员提出了极高的要求。开发者不仅要同时具备软件和硬件的知识和经验,而且还要不断地学习、更新自己,以便跟上嵌入式系统日新月异的发展。研究前人的总结和动手实践是不断提高自己的有效途径。虽然市面上已经有多种设备驱动的书籍,但本书在总结Linux设备驱动程序方面仍然非常具有特色。它用理论联系实际,尤其是提供了大量的实例,对读者深入地理解并掌握各种驱动程序的编写大有裨益。
      ——飞思卡尔半导体(中国)有限公司数字网络软件技术方案部总监  杨欣欣博士


      一位优秀的设备驱动开发工程师需要具备多年嵌入式软件和硬件开发经验的积累,本书针对Linux设备驱动开发相关的设计思想、框架、内核,深入浅出,结合代码,从理论到实践进行重点讲解。毫无疑问,本书可谓一把通向设备驱动大师殿堂之门的金钥匙,它将激发你的味蕾,带你“品尝”嵌入式设备驱动开发这道“美味佳肴”,掩卷沉思,意味深长。
      ——ARM中国在线社区经理   宋斌


      作者长期从事嵌入式Linux开发和教学工作,擅长Linux驱动开发,并跟踪开源软件和嵌入式处理器技术的最新发展,撰写本书,书中内容新鲜实用。作者针对ARM和移动便携式设备的兴起,在书中添加了ARM Linux 设备树和Linux电源管理系统架构及驱动的内容,书中关于Linux设备驱动的软件架构思想的章节也很有特色。
      ——中国软件行业协会嵌入式系统分会副理事长 何小庆


    封面:


    展开全文
  • 本博实时更新《Linux设备驱动开发详解(第3版)》(即《Linux设备驱动开发详解:基于最新的Linux 4.0内核》)的最新进展。 目前已经完成稿件。 2015年8月9日,china-pub开始上线预售: ... 2015年8月20日,各路朋友报喜...

    本博实时更新《Linux设备驱动开发详解(第3版)》的最新进展。 目前已经完成稿件。

    2015年8月9日,china-pub开始上线预售:

    http://product.china-pub.com/4733972

    2015年8月20日,各路朋友报喜说已经拿到了书。

    本书已经rebase到开发中的Linux 4.0内核,案例多数基于多核CORTEX-A9平台

    本书微信公众号二维码, 如需联系请扫描下方二维码

    [F]是修正或升级;[N]是新增知识点;[D]是删除的内容

     

    第1章 《Linux设备驱动概述及开发环境构建》
    [D]删除关于LDD6410开发板的介绍
    [F]更新新的Ubuntu虚拟机
    [N]添加关于QEMU模拟vexpress板的描述

     

    第2章 《驱动设计的硬件基础》

    [N]增加关于SoC的介绍;
    [N]增加关于eFuse的内容;
    [D]删除ISA总线的内容了;
    [N]增加关于SPI总线的介绍;
    [N]增加USB 3.0的介绍;
    [F]修正USB同步传输方式英文名;
    [D]删除关于cPCI介绍;
    [N]增加关于PCI Express介绍;
    [N]增加关于Xilinx ZYNQ的介绍;
    [N]增加SD/SDIO/eMMC的章节;
    [D]删除“原理图分析的内容”一节;
    [N]增加通过逻辑分析仪看I2C总线的例子;

     

    第3章 《Linux内核及内核编程》

    [N]新增关于3.X内核版本和2015年2月23日 Linux 4.0-rc1
    [N]新增关于内核版本升级流程以及Linux社区开发模式讲解
    [N]新增关于Linux内核调度时间的图式讲解
    [N]新增关于Linux 3.0后ARM架构的变更的讲解
    [N]新增关于TASK_KILLABLE状态的简介
    [N]新增Linux内存管理图式讲解

    [F]修正Kconfig和Makefile中的一些表述
    [D]删除关于x86启动过程讲解
    [N]新增ARM Linux启动过程讲解
    [N]新增关于likely()和unlikely()讲解
    [N]新增toolchain的讲解,以及toolchain的几种浮点模式


    第4章 《Linux内核模块》
    [F]改正关于模块使用非GPL license的问题;
    [F]修正关于__exit修饰函数的内存管理

    第5章 《Linux文件系统与设备文件》
    [F]修正关于文件系统与块设备驱动关系图;
    [N]增加应用到驱动的file操作调用图;
    [N]增加通过netlink接受内核uevent的范例;
    [N]增加遍历sysfs的范例;

    [N]增加为kingston U盘编写udev规则的范例;
    [F]更新udev规则,以符合新版本;
    [N]增加udevadm的讲解;
    [N]高亮Android vold
     
    第6章 《字符设备驱动》
    [F]更新file_operations的定义,升级ioctl()原型;
    [N]增加关于Linux access_ok()的讲解以及Linux内核安全漏洞的说明;
    [F]修正globalmem的编码风格;
    [F]在globalmem支持2个以上实例的时候,从直接2个实例,升级为支持N个实例;

    第7章 《Linux设备驱动中的并发控制》
    [N]绘图深入讲解单核和多核下的各种竞态;
    [N]增加关于编译乱序,执行乱序,编译屏障和内存屏障的讲解;
    [N]增加关于ARM LDREX/STREX指令的讲解;
    [N]对spin_lock单核和多核的使用场景进行深入分析;

    [F]重新整理RCU的讲解方法和实例;
    [F]明确指明信号量已过时;
    [F]将globalmem中使用的信号量换为mutex。


    第8章 《Linux设备驱动中的阻塞与非阻塞I/O》
    [N]新增阻塞和非组塞的时序图
    [F]修正关于等待队列头部、等待队列元素的一些中文说法
    [N]添加等待队列的图形描述
    [F]修正globalfifo的编码风格
    [F]修正globalfifo可读可写的if判断为while判断
    [N]新增select的时序图
    [N]新增EPOLL的章节


    第9章 《Linux设备驱动中的异步通知与异步I/O》
    [F]修正关于glibc AIO支持
    [F]修正关于内核AIO支持
    [F]修正驱动AIO接口
    [D]删除关于驱动AIO支持的错误实例
    [N]高亮C10问题

    第10章 《中断与时钟》
    [N]增加关于ARM GIC的讲解
    [N]增加关于irq_set_affinity() API的讲解
    [N]增加关于devm_request_irq() API的讲解
    [N]增加关于request_any_context_irq() API的讲解

    [F]修正interrupt handler原型
    [F]修正work queue原型
    [N]新增关于Concurrency-managed workqueues讲解
    [N]增加关于ksoftirqd讲解
    [N]增加关于request_threaded_irq()讲解
    [D]删除s3c6410 rtc驱动中断实例
    [N]新增GPIO按键驱动中断实例
    [N]新增hrtimer讲解和实例
    [F]修正second设备编码风格

    第11章 《内存与I/O访问》
    [F]修正关于页表级数的描述,添加PUD
    [F]修正page table walk的案例,使用ARM Linux pin_page_for_write
    [N]新增关于ARM Linux内核空间虚拟地址分布
    [F]修正关于内核空间与用户空间界限
    [N]新增关于DMA、NORMAL和HIGHMEM ZONE的几种可能分布
    [N]新增关于buddy的介绍
    [F]修正关于用户空间malloc的讲解
    [N]增加mallopt()的案例
    [N]增加关于devm_ioremap、devm_request_region()和devm_request_mem_region()的讲解
    [N]增加关于readl()与readl_relaxed()的区别,writel()与writel_relaxed()的区别

    [F]更新vm_area_struct的定义
    [F]修正nopage() callback为fault() callback
    [N]增加io_remap_pfn_range()、vm_iomap_memory()讲解
    [F]强调iotable_init()静态映射目前已不太推荐
    [N]增加关于coherent_dma_mask的讲解
    [N]讲解dma_alloc_coherent()与DMA ZONE关系
    [N]提及了一致性DMA缓冲区与CMA的关系
    [N]增加关于dmaengine驱动和API的讲解

     

    第12章 《工程中的Linux设备驱动》
    [F]更名为《Linux设备驱动的软件架构思想》;
    [N]本章新增多幅图片讲解Linux设备驱动模型;
    [N]新增内容详细剖析为什么要进行设备与驱动的分离,platform的意义;
    [N]新增内容详细剖析为什么Linux设备驱动要分层,枚举多个分层实例;
    [N]新增内容详细剖析Linux驱动框架如何解耦,为什么主机侧驱动要和外设侧驱动分离;
    [N]DM9000实例新增关于在dts中填充平台信息的内容;
    [N]新增内容讲解驱动核心层的3大功能;
    [N]新增内容以面向对象类泛化对比Linux驱动;
    [N]SPI案例部分新增通过dts填充外设信息;

    [F]从tty, LCD章节移出架构部分到本章

     

    第13章 《Linux块设备驱动》
    [N]介绍关于block_device_operations的check_events成员函数
    [N]添加关于磁盘文件系统,I/O调度关系的图形
    [F]更新关于request_queue、request、bio、segment关系的图形
    [F]淘汰elv_next_request
    [F]淘汰blkdev_dequeue_request
    [N]添加关于blk_start_request描述
    [F]淘汰Anticipatory I/O scheduler
    [N]添加关于ZRAM块设备驱动实例
    [F]更新针对内核4.0-rc1的vmem_disk
    [N]添加关于vmem_disk处理I/O过程的图形
    [N]增加关于Linux MMC子系统的描述

     

    第14章 《Linux终端设备驱动》
    [D]整章全部删除,部分架构内容前移到第12章作为驱动分层实例

     

    第15章 《Linux I2C核心、总线与设备驱动》

    [F]修正i2c_adpater驱动的案例
    [N]增加关于在device tree中增加i2c设备的方法的描述

     

    第16章 《Linux网络设备驱动》

    [F]本章顺序从第16章前移到第14章
    [N]澄清sk_buff head、data、tail、end指针关系
    [F]更新sk_buff定义
    [F]澄清skb_put、skb_push、skb_reserve
    [N]增加netdev_priv的讲解,加入实例
    [N]增加关于get_stats()可以从硬件读统计信息的描述

    [F]修正关于net_device_stats结构体的定义位置
    [F]修正关于统计信息的更新方法

     

    第17章 《Linux音频设备驱动》

    [D] 本章直接删除

     

    第18章 《LCD设备驱动》

     

    [D] 本章直接删除,部分架构内容前移到第12章

     

    第19章 《Flash设备驱动》

    [D] 本章直接删除

     

    第20章 《USB主机与设备驱动》
    [F]前移到第16章;
    [F]更名为《USB主机、设备与Gadget驱动》;
    [N]增加关于xHCI的介绍;
    [F]修正usb gadget驱动为function驱动;
    [D]删除OHCI实例;
    [N]添加EHCI讲解和Chipidea EHCI实例;
    [F]修正iso传输实例;
    [F]修正usb devices信息到/sys/kernel/debug/usb/devices
    [N]介绍module_usb_driver;
    [N]介绍usb_function;
    [N]介绍usb_ep_autoconfig;
    [N]介绍usb_otg;

    [D]删除otg_transceiver;

     

    第21章 《PCI设备驱动》
    [D]整章删除

     

    第22章 《Linux设备驱动的调试》

    [F]变为第21章;

    [D]把实验室环境建设相关的节移到第3章;

    [F]修正关于gdb的set step-mode的含义讲解;

    [F]增加关于gdb的set命令的讲解;

    [F]增加gdb call命令的案例

    [D/N]删除手动编译工具链的代码,使用crosstool-ng;
    [N]更新toolchain的下载地址(codesourcery -> memtor),加入linaro下载地址;
    [N]增加pr_fmt的讲解;
    [N]增加关于ignore_loglevel bootargs的讲解;
    [N]增加EARLY_PRINTK和DEBUG_LL的讲解;

    [F]调整proc的范例,创建/proc/test_dir/test_rw;
    [N]修正关于3.10后内核proc实现框架和API的变更;
    [N]增加关于BUG_ON和WARN_ON的讲解
    [F]不再以BDI-2000为例,改为ARM DS-5;
    [N]增加关于ARM streamline性能分析器的介绍;
    [N]增加使用qemu调试linux内核的案例;
    [F]调整Oops的例子,使用globalmem,平台改为ARM;
    [F]更新LTT为LTTng。

     

    第23章 《Linux设备驱动的移植》
    [D]整章删除

     

    全新的章节

     

    第17章  《I2C、SPI、USB架构类比》

     

    本章导读

    本章类比I2C、SPI、USB的结构,从而更进一步帮助读者理解本书第12章的内容,也进一步实证Linux驱动万变不离其宗的道理。

     

    第18章  《Linux设备树(Device Tree)》

     

    本章导读

    本章将介绍Linux设备树(Device Tree)的起源、结构和因为设备树而引起的驱动和BSP变更。

    18.1节阐明了ARM Linux为什么要采用设备树。

    18.2节详细剖析了设备树的结构、结点和属性,设备树的编译方法以及如何用设备树来描述板上的设备、设备的地址、设备的中断号、时钟等信息。

    18.3节讲解了采用设备树后,驱动和BSP的代码需要怎么改,哪些地方变了。

    18.4节补充了一些设备树相关的API定义以及用法。

    本章是相对《Linux设备驱动开发详解(第2版)》全新的一章内容,也是步入内核3.x时代后,嵌入式Linux工程师必备的知识体系。

     

     

     

    第19章  《Linux的电源管理》

     

    本章导读

    Linux在消费电子领域的应用已经铺天盖地,而对于消费电子产品而言,省电是一个重要的议题。

    本章将介绍Linux设备树(Device Tree)的起源、结构和因为设备树而引起的驱动和BSP变更。

    19.1节阐述了Linux电源管理的总体架构。

    19.2~19.8节分别论述了CPUFreq、CPUIdle、CPU热插拔以及底层的基础设施Regulator、OPP以及电源管理的调试工具PowerTop。

    19.9节讲解了系统Suspend to RAM的过程以及设备驱动如何提供对Suspend to RAM的支持。

    19.10节讲解了设备驱动的Runtimesuspend。

    本章是相对《Linux设备驱动开发详解(第2版)》全新的一章内容,也是Linux设备驱动工程师必备的知识体系。

     

     

     

    第20章 《Linux芯片级移植与底层驱动》

     

    本章导读

    本章主要讲解,在一个新的ARM SoC上,如何移植Linux。当然,本章的内容也适合MIPS、PowerPC等其他的体系架构。

    第20.1节先总体上介绍了Linux 3.x之后的内核在底层BSP上进行了哪些优化。

    第20.2节讲解了如何提供操作系统的运行节拍。

    第20.3节讲解了中断控制器驱动,以及它是如何为驱动提供标准接口的。

    第20.4节讲解多核SMP芯片的启动。

    第20.6~20.9节分别讲解了作为Linux运行底层基础设施的GPIO、pinctrl、clock和dmaengine驱动。

    本章相对《Linux设备驱动开发详解(第2版)》几乎是全新的一章内容,有助于工程师理解驱动调用的底层API的来源,以及直接有助于进行Linux的平台移植。

     

    展开全文
  • 本书介绍了Linux设备驱动开发理论、框架与实例,详细说明了自旋锁、信号量、完成量、中断顶/底半部、定时器、内存和I/O映射以及异步通知、阻塞I/O、非阻塞I/O等Linux设备驱动理论,以及字符设备、块设备、tty设备、I2...

    本书介绍了Linux设备驱动开发理论、框架与实例,详细说明了自旋锁、信号量、完成量、中断顶/底半部、定时器、内存和I/O映射以及异步通知、阻塞I/O、非阻塞I/O等Linux设备驱动理论,以及字符设备、块设备、tty设备、I2c设备、LCD设备、音频设备、USB设备、网络设备、PCI设备等Linux设备驱动架构中各个复杂数据结构和函数的关系,并讲解了Linux驱动开发的大量实例,使读者能够独立开发各类Linux设备驱动。

     

    【备注:本书第11页,第六行链接已经失效,替换为:http://pan.baidu.com/s/1cFrl2e 密码:ezs2】

    作者简介

      宋宝华,Linux布道者,知名嵌入式系统专家,《Essential Linux Device Drivers》译者。作为较早从事Linux内核与设备驱动研究的专家之一,他在众多国内外知名企业开展Linux技术培训。他也是一位活跃的Linux开发者和深度实践者,为Linux官方内核贡献了大量的Linux源码并承担代码审核工作。至今已向Linux官方内核提交逾数万行代码和几百个补丁。他的《Linux设备驱动开发详解》系列书在嵌入式Linux开发者中有口皆碑,是众多Linux书籍中为数不多的畅销书。

     
     
    限个人学习使用,不得用于商业用途,请在下载后24小时内删除。
    备注:资源来自网络,如有不合理可私信我,秒删。
    电子书 Linux设备驱动开发详解:基于最新的Linux 4.0内核.pdf 宋宝华 免费下载
    https://page55.ctfile.com/fs/14299555-204231232
     
     

    展开全文
  • Linux设备驱动中的并发控制 有两种可能的原因会造成程序出错,一种可能性是编译乱序,另一种可能性是执行乱序。 处理器为了解决多核间一个核的内存行为对另一个核可见的问题,引入了一些内存屏蔽的指令。ARM处理器...

    Linux设备驱动中的并发控制

    有两种可能的原因会造成程序出错,一种可能性是编译乱序,另一种可能性是执行乱序。

    处理器为了解决多核间一个核的内存行为对另一个核可见的问题,引入了一些内存屏蔽的指令。ARM处理器的屏蔽指令包括:

    DMB(数据内存屏障):在DMB之后的显式内存访问执行前,保证所有在DMB指令之前的内存访问完成;

    DSB(数据同步屏障):等待所有在DSB指令之前的指令完成(位于此指令前的所有显式内存访问均完成,位于此指令前的所有缓存、跳转预测和TLB维护操作全部完成);

    ISB(指令同步屏障):Flush流水线,使得所有ISB之后执行的指令都是从缓存或者内存中获得的。

     

    Linux内核提供了一系列函数来实现内核中的原子操作,分为两类:整型原子操作和位原子操作。

    使用原子变量使设备只能被一个进程打开。

    例:

    static atomic_t xxx_available = ATOMIC_INIT(1);
    static int xxx_open(struct inode *inode, struct file *filp)
    {       
    	…
    	if(!atomic_dec_and_test(&xxx_available)){
                       atomic_inc(&xxx_available);
                       return–EBUSY;
    	}
    	…
    	return 0;
    }
    static int xxx_release(struct inode *inode, struct file*filp)
    {
    	atomic_inc(&xxx_available);
    	return 0;
    }

    自旋锁(Spin Lock的衍生、读写自旋锁、顺序锁)与RCU(Read-Copy-Update,读-复制-更新)

    自旋锁,既保证排他性,也能处理好内存屏障。主要针对SMP或单CPU但内核可抢占的情况,对于单CPU和内核不支持抢占的系统,自旋锁退化为空操作。

    在得到锁的代码路径在执行临界区的时候,还可能受到中断和底半部(BH)的影响。为了防止这种影响,就衍生除了一套自旋锁机制。

    使用自旋锁需要注意的问题:

    (1)      只有在占用锁的时间极短的情况下,使用自旋锁才是合理的。当临界区很大,或有共享设备的时候,需要较长时间占用锁,使用自旋锁会降低系统的性能。

    (2)      自旋锁可能导致死锁。最常见的情况是递归使用一个自旋锁。

    (3)      在自旋锁锁定期间不能调用可能引起进程调度的函数。如果进程获得自旋锁之后再阻塞,如调用copy_from_user()、kmalloc()、msleep()等函数,则可能导致内核的崩溃。

    (4)      在强调跨平台的概念时,CPU视为多核,spin_lock_irpsave()不能屏蔽另一个核的中断,所以另一个核就可能造成并发问题。因此,无论如何,我们在中断服务程序里也应该调用spin_lock()。

    RCU的机制跟自旋锁相反。读自旋锁是等所有进程或中断释放自旋锁后,再拿到自旋锁后修改数据。RCU是直接制造一个新的节点M,把N的内容复制给M,之后再修改M上的数据,并用M代替N原本在链表的位置。之后进程等待在链表前期已经存在的所有读端结束后(即宽限期,通过synchronize_rcu()API完成),在释放原来的N。

    但是RCU不能代替读写锁,因为RCU写执行单元之间的同步开销比较大,它也必须使用某种锁机制来同步并发的其他写执行单元的修改操作。

    函数call_rcu()也由RCU写执行单元调用,与synchronize_rcu()不同的是,它不会使写执行单元阻塞,因而可以在中断上下文或软中断使用。

    信号量(semaphore)是操作系统中最典型的用于同步和互斥的手段,信号量的值可以是0、1或者n。信号量与操作系统中的经典概念PV操作对应。

    互斥体。尽管信号量已经可以实现互斥的功能,但是“正宗”的mutex在Linux内核中还是真实地存在着。

    总结自旋锁和互斥体选用的3项原则:

    (1)      若临界区比较小,宜使用自旋锁,若临界区很大,应使用互斥体。

    (2)      互斥体所保护的临界区可以包含可能引起阻塞的代码,而自旋锁则绝对要避免用来保护包含这样代码的临界区。

    (3)      互斥体存在于进程上下文,因此,如果被保护的共享支援需要在中断或者软中断情况下使用,则在互斥体和自旋锁之间只能选择自旋锁。当然,如果一定要使用互斥体,则只能通过mutex_trylock()方式进行,不能获取就立即返回以避免阻塞。

    Linux提供了完成量(Completion),它用于一个执行单元等待另一个执行单元执行完某事。

     

    增加并发控制后的globalmem的设备驱动。

    在globalmem()读写函数中,由于调用了copy_from_user()等可能导致阻塞的函数,因此不能使用自旋锁,宜使用互斥体。

    驱动工程师习惯将某设备锁使用的自旋锁、互斥体等辅助手段也放在设备结构中。

    struct globalmem_dev{
             …
             struct mutexmutex;
    }

    加载函数中添加互斥体初始化:

    mutex_init(&globalmem_devp->mutex);

    globalmem的读写操作中,在访问共享资源时,先获取互斥体,访问完成后,释放互斥体。

    mutex_lock(&dev->mutex);
    if(copy_from_user(buf, dev->mem + p, count)){     
    <span style="white-space:pre">	</span>ret = -EFAULT;
    }else
    …
    mutex_unlock(&dev->mutex);

    如果在读写的同时,另一个执行单元执行MEM_CLEAR IO控制命令,也会到导致全局内存的混乱,因此globalmem_ioctl()修改如下:

    …
    case MEM_CLEAR:
             mutex_lock(&dev->mutex);
             memset(dev->mem,0 , GLOBALMEM_SIZE);
             mutex_unlock(&dev->mutex);
    …


    展开全文
  • 第二章 Linux 的内核结构及构建 ----&amp;amp;amp;amp;amp;amp;amp;gt;这一章是自己总结的 1、内核结构(主要是下面这几个部分) 系统调用接口&amp;amp;amp;amp;amp;amp;amp;lt;—&amp;amp;amp;...

    第二章 Linux 的内核结构及构建

    • ---->这一章是自己总结的

    1、内核结构(主要是下面这几个部分)

    • 系统调用接口<–>System call interface
    • 进程管理<------>Process management
    • 内存管理<------>Memory management
    • 虚拟文件系统<–>VFS
    • 网络设备<------>Net
    • 进程间通信<---->IPC
    • 设备驱动<------>Drivers
      • -------->具体对应的目录见书上59页

    2、Makefiles and build system of kernel–kbuild

    2.1 makefile包含五大部分

    • The top Makefile:内核源码根目录下的Makefile,所有内核代码编译的入口。它负责两类东西的编译:

      • vmlinux:内核映像,Image->zImage -> boot.img,img是内核的常住居民。随系统启动而运行,直到系统关机。
      • modules:内核模块 xxx.ko,这种形式,也是内核源码的一种二进制形式,从本质上来说和内核映像是一样。但是ko是以普通文件的形式存在的,不随系统启动而运行,在系统需要你的时候 insmod xxx.ko,不需要你的时候就rmmod xxx.ko.如: camera.ko,ko形式多见于外设驱动它递归进入到内核源码树子目录去构建这些目标,应该至少包含一个arch的makefile和一个arch/$(ARCH)/Makefile(跟具体硬件平台相关)
    • .config:内核源码根目录下,内核编译的配置文件,该文件直接决定哪些文件编译、怎么编译,内核配置文件包含像下面这些选项:

      • CONFIG_EXPERIMENTAL=y
      • CONFIG_BROKEN_ON_SMP=y
      • CONFIG_INIT_ENV_ARG_LIMIT=32
      • CONFIG_CROSS_COMPILE=“arm-linux-”
    • arch/$(ARCH)/Makefile:体系结构相关的Makefile,决定底层CPU相关的源码如何编译。为top Makefile提供具体硬件体系结构相关的信息。

    • scripts/Makefile.*:包含了一些通用的Makefile模式,函数,脚本等等。供其他Makefile包含

    • kbuild Makefiles_:每个子目录有一个kubild makefile,决定哪些文件编译到vmlinux(built-in),哪些编成在ko,kbuild(内核编译系统)内置了几个变量

      • obj-y: 这个变量指定的.o文件列表,最终编译到vmlinux中去
        obj-y := a.o b.o c.o
        a-y = 1.o 2.o

        • 1.o <- 1.c,2.o < 2.c
          ->a.o
        • b.o <- b.c,c.o <- c.c
          => vmlinux -> … -> boot.img
      • obj-m:obj-m这个变量指定的.o文件列表,kbuild最终会为每个.o生成一个同名的ko文件

        • obj-m := a.o b.o,a.o -> a.ko,b.o -> b.ko
      • 语法:目标名-y/目标名-objs:生成"目标名"所依赖的.o文件列表

        • obj-m := a.o b.o

          • a.c(a.s) ->a.o -> a.ko
          • b.c(b.s) ->b.o -> b.ko
        • obj-m := sb.o nb.o

        • sb-y := a.o b.o c.o

          • a.o <- a.c(a.s)
          • b.o <- b.c(b.s)
          • c.o <- c.c(c.s)
            • =>sb.o -> sb.ko
            • nb.c(nb.s) -> nb.o -> nb.ko
        • obj-$(CONFIG_XXX) += sb.o

          • kbuild只认  obj-y obj-m

          • sb.o编还是不编,得看变量CONFIG_XXX的值

          • if CONFIG_XXX = y sb.o编,而且编进vmlinux

          • if CONFIG_XXX = m sb.o编成sb.ko

          • else other , 不编

             obj-m += camera.o
             camera-objs += a.o b.o
             camera-$(CONFIG_MEIYANG) += mei.o  
            
        • obj-$(CONFIG_XXX) += xxx/

          • 表示你如果选择了CONFIG_XXX请到子目录xxx下面去读Makefile

    2.2 内核编译的两大步骤

    • 1、配置
      • make menuconfig:=> 生成一个人性化的配置菜单树(供你选择)
        • sudo apt-get install libncurses5-dev
        • 目的是生成一个 .config (配置文件,决定哪些文件编译,哪些不编译)
          • CONFIG_FOO = y
          • CONFIG_MM = m
          • CONFIG_XX = n
    • 2、编译 make(sudo ./mk -k)
      • a. 先读.config里面的内容,把相应的变量值替换到Makefile中去
        • obj-$(CONFIG_FOO) += foo.o
        • obj-$(CONFIG_MM) += mm.o
        • obj-$(CONFIG_XX) += xx.o
        • ----->
          • obj-y += foo.o
          • obj-m += mm.o
          • obj-n += xx.o
      • b. 编译
        • foo.o -> foo.o -> vmlinux
        • mm.c -> mm.o -> mm.ko
    • 3、一个例子
      • 先准备好下面的文件:my_char_drivers/hello.c,Kconfig,Makefile
      • (1) 把my_char_drivers整个目录拷贝到  内核源码目录的 drivers/char
      • (2) 修改 drivers/char/Kconfig 增加一行,让其包含my_char_drivers/Kconfig
        • vim dirvers/char/Kconfig 增加一行
        • source “drivers/char/my_char_drivers/Kconfig”
      • (3) 修改 drivers/char/Makefile 增加一行,让其包含my_char_drivers/Makefile
        • vim drivers/char/Makefile 增加-行
        • obj-$(CONFIG_zhoulong_drivers) += my_char_drivers/

    2.3 .config的内容

    • Kconfig
      • Kconfig是作为.config的配置文件
      • 内容是用kconfig特有的语言编写
      • 配置信息的数据库是一个配置选项的集合
    • Kconfig 语法
      • config
        • config <symbol>
        • <config options>
          • 关键字config开始一个新的配置入口,紧接着的一行是上一个选项的属性,举例:

             config FOO
                 tristate
                 prompt "a test"
                 depends on BAR
                 default m
                 help
                 "a example for config entry"
            
      • menuconfig
        • menuconfig <symbol>
        • <config options>
      • menu/endmenu
        • menu “some prompt info”
        • <menu options>
        • <menu block>
        • endmenu
      • if/endif
        • if <expr>
        • endif
      • source
        • source “xxx/xxx/Kconfig”
      • choice/endchoice
        • choice [symbol]
        • <choice options>
        • <choice block>
        • endchoice
          • 一个选择只能是一个布尔值或三态,布尔选项只允许单个配置选项被选中,但是三态选择还允许将任意数量的配置项设置为“m”。
          • 这个可以用在如果一个硬件有多个驱动程序存在并且只有一个驱动程序可以编译进内核,但是所有的驱动程序可以编译成模块
      • comment
        • comment “some prompt info”
        • <comment options>
          • 这定义了一个注释,它在配置过程中显示给用户,并且也与输出到输出文件。唯一可能的选项是依赖项。

    3、An example

    4、Process of making zImage(uImage)

    第三章 Linux内核及内核编程

    3.2 linux 2.6以后内核的特点(相对于linux2.4)

    1.新的调度器

    • 内核 2.6 的早期采用了 O(1) 算法,之后转移到 CFS(Completely Fair Scheduler,完全公平调度)算法。在 Linux
      3.14 中,也增加了一个新的调度类:SCHED_DEADLINE,它实现了 EDF(Earliest Deadline First,最早截止期限优先)调度算法。

    2.内核抢占

    • Linux 2.6 以后的内核版本还是存在一些不可抢占的区间,如中断上下文、软中断上下文和自旋锁锁住的区间
      在这里插入图片描述
      可以看到,在 Linux 2.4 的内核中,在 IRQ1 的中断服务程序唤醒 RT(实时)任务后,必须要等待前面一个 Normal(普通)任务的系统调用完成,返回用户空间的时候,RT 任务才能切入;而在 Linux 2.6 内核中,Normal 任务的关键部分(如自旋锁)结束的时候,RT 任务就从内核切入了。

    3.改进的线程模型

    • Linux 2.6 以后版本中的线程采用 NPTL(Native POSIX Thread Library,本地 POSIX 线程库)模型,操作速度得以极大提高,内核本身也增加了 FUTEX(Fast Userspace Mutex,快速用户态互斥体),从而减小多线程的通信开销。

    4.虚拟内存的变化

    • 从虚拟内存的角度来看,新内核融合了 r-map(反向映射)技术,显著改善虚拟内存在一定大小负载下的性能。反向映射即可以通过页结构体快速寻找到页面的映射。

    5.文件系统

    • Linux 2.6 版内核增加了对日志文件系统功能的支持,还包括对扩展属性及 POSIX 标准访问控制的支持。ext2/ext3/ext4 作为大多数 Linux 系统默认安装的文件系统,在 Linux 2.6 版内核中增加了对扩展属性的支持,可以给指定的文件在文件系统中嵌入元数据。
    • 在文件系统方面,当前的研究热点是基于 B 树的 Btrfs,Btrfs 称为是下一代 Linux 文件系统,它在扩展性、数据一致性、多设备管理和针对 SSD 的优化等方面都优于 ext4

    6.音频

    • 高级 Linux 音频体系结构(Advanced Linux Sound Architecture,ALSA),ALSA 支持 USB 音频和 MIDI 设备,并支持全双工重放等功能

    7.总线、设备和驱动模型

    • 总线是三者联系起来的基础,通过一种总线类型,将设备和驱动联系起来。总线类型中的 match() 函数用来匹配设备和驱动,当匹配操作完成之后就会执行驱动程序中的probe() 函数。

    8.电源管理

    9.联网和 IPSec

    • 改进了对 IPv6 的支持

    10. 用户界面层

    11. Linux 3.0 后 ARM 架构的变更

    • ARM Linux 的代码在时钟、DMA、pinmux、计时器刻度等诸多方面都进行了优化和调整,也删除了arch/arm/mach-xxx/include/mach 头文件目录,以至于 Linux 3.7 以后的内核可以支持多平台,即用同一份内核镜像运行于多家 SoC 公司的多个芯片,实现“一个Linux 可适用于所有的 ARM 系统”。

    3.3 Linux 内核的组成

    3.3.1 Linux 内核源代码的目录结构

    目录 功能
    arch 包含和硬件体系结构相关的代码,每种平台占一个相应的目录,如 i386、arm、arm64、powerpc、mips 等。存放的是各个平台以及各个平台的芯片对 Linux 内核进程调度、内存管理、中断等的支持,以及每个具体的 SoC 和电路板的板级支持代码。
    block 块设备驱动程序 I/O 调度
    crypto 常用加密和散列算法(如 AES、SHA 等),还有一些压缩和 CRC 校验算法
    documentation 内核各部分的通用解释和注释
    drivers 设备驱动程序,每个不同的驱动占用一个子目录,如 char、block、net、mtd、i2c 等。
    fs 所支持的各种文件系统,如 EXT、FAT、NTFS、JFFS2 等
    include 头文件,与系统相关的头文件放置在 include/linux 子目录下
    init 内核最核心的部分,包括进程调度、定时器等,而和平台相关的一部分代码放在 arch/*/kernel 目录下
    lib 库文件代码
    mm 内存管理代码,和平台相关的一部分代码放在 arch/*/mm 目录下
    net 网络相关代码,实现各种常见的网络协议
    scripts 用于配置内核的脚本文件
    security 主要是一个 SELinux 的模块
    sound ALSA、OSS 音频设备的驱动核心代码和常用设备驱动
    usr 实现用于打包和压缩的 cpio 等
    include 内核 API 级别头文件

    3.3.2 Linux 内核的组成部分

    • 进程调度
      • 在 Linux 内核中,使用 task_struct 结构体来描述进程,该结构体中包含描述该进程内存资源、文件系统资源、文件资源、tty 资源、信号处理等的指针。Linux 的线程采用轻量级进程模型来实现,在用户空间通过 pthread_create() API 创建线程的时候,本质上内核只是创建了一个新的 task_struct,并将新task_struct 的所有资源指针都指向创建它的那个 task_struct
        的资源指针。
    • 内存管理
      • 一般而言,32 位处理器的 Linux 的每个进程享有 4GB 的内存空间,0 ~ 3GB 属于用户空间,3 ~ 4GB 属于内核空间,内核空间对常规内存、I/O 设备内存以及高端内存有不同的处理方式。上次CVTE笔试考了下面这个图(画出来)
        在这里插入图片描述
      1. 虚拟文件系统
      • Linux 虚拟文件系统隐藏了各种硬件的具体细节,为所有设备提供了统一的接口。而且,它独立于各个具体的文件系统,是对各种文件系统的一个抽象。它为上层的应用程序提供了统一的 vfs_read()、vfs_write() 等接口,并调用具体底层文件系统或者设备驱动中实现的 file_operations 结构体的成员函数。
    • 4.网络接口(略)
    • 5.进程间通信(略)

    3.3.3 Linux 内核空间与用户空间

    • ARM 处理器分为 7 种工作模式:

    3.4 Linux 内核的编译及加载

    3.4.1 Linux 内核的编译

    • Linux 驱动开发者需要牢固地掌握 Linux 内核的编译方法以为嵌入式系统构建可运行的Linux 操作系统映像。
      • 运行 make menuconfig 等时,配置工具首先分析与体系结构对应的 /arch/xxx/Kconfig 文件(xxx 即为传入的 ARCH 参数),/arch/xxx/Kconfig 文件中除本身包含一些与体系结构相关的配置项和配置菜单以外,还通过 source 语句引入了一系列 Kconfig 文件,而这些 Kconfig又可能再次通过 source 引入下一层的 Kconfig,配置工具依据 Kconfig 包含的菜单和条目即可描绘出一个如图 3.9 所示的分层结构。

    3.4.2 Kconfig 和 Makefile

    • 在 Linux 内核中增加程序需要完成以下 3 项工作
      • 将编写的源代码复制到 Linux 内核源代码的相应目录中
      • 在目录的 Kconfig 文件中增加关于新源代码对应项目的编译配置选项
      • 在目录的 Makefile 文件中增加对新源代码的编译条目

    3.4.3 Linux 内核的引导(ARM Linux 为例)

    • 。一般的 SoC 内嵌入了 bootrom,上电时 bootrom 运行。对于 CPU0 而言,bootrom 会去引导 bootloader,而其他 CPU 则判断自己是不是 CPU0,进入 WFI 的状态等待 CPU0 来唤醒它。CPU0 引导 bootloader,bootloader 引导Linux 内核,在内核启动阶段,CPU0 会发中断唤醒 CPU1,之后 CPU0 和 CPU1 都投入运行。CPU0 导致用户空间的 init 程序被调用,init 程序再派生其他进程,派生出来的进程再派生其他进程。CPU0 和 CPU1 共担这些负载,进行负载均衡。

    3.5 Linux 下的 C 编程特点

    3.5.1 Linux 编码风格

    • 在内核源代码下存在一个文件 Documentation/CodingStyle,进行了比较详细的描述

    • 在 Windows 程序中,习惯以如下方式命名宏、变量和函数

        #def ine PI 3.1415926  /* 用大写字母代表宏 */
        int minValue, maxValue; /* 变量:第一个单词全小写,其后单词的第一个字母大写 */
        void SendData(void);  /* 函数:所有单词第一个字母都大写 */
      
    • 在 Linux 中它会被命名为:

        #def ine PI 3.1415926
        int min_value, max_value;
        void send_data(void);
      

    3.6 工具链

    • 见书本page100-page101

    第4章 Linux内核模块

    4.9 模块的编译

    • 例:
    KVERS = $(shell uname -r)
    
    #Kernel module
    obj-m += hello.o
    
    #Specify flags for the module compilation
    #EXTRA_CFLAGS = -g -O0
    
    build:kernel_modules
    kernel_modules:
        make -C /lib/modules/$(KVERS)/build M=$(CURDIR) modules
    clean:
        make -C /lib/modules/$(KVERS)/build M=$(CURDIR) clean
    

    。。。未完

    。。。。。。。

    。。。。。。。

    展开全文
  • Linux从未停歇脚步。Linus Torvalds,世界上最伟大的程序员之一,Linux内核的创始人,Git的缔造者,仍然在没日没夜的合并补丁,升级内核。做技术,从来没有终南捷径,拼的就是坐冷板凳的傻劲。 这是一个连阅读都被...
  • 问题描述关于《Linux设备驱动开发详解:基于最新的Linux 4.0内核》一书1.华章分社在没有征得作者同意的情况下,修改了作者稿件,其后也未发给作者审核,造成许多错误...
  • 区别于Linux4.0之前的字符设备驱动结构,4.0采用cdev注册字符设备。 一、构造一个字符设备结构体,用于cdev的初始化 struct led_dev_t{ struct cdev cdev; }; 二、__init 入口函数 1.设备号的处理 dev_t led_devno...
  • 设备驱动最通俗的解释就是“驱使硬件设备行动”(1)无操作系统时的设备驱动在没有操作系统的情况下,设备驱动的接口被直接提交给应用软件工程师,应用软件没有跨越任何层次就直接访问设备驱动的接口。(2)有操作系统时的...
  • 1 Linux设备驱动概述及开发环境构建 1.1 设备驱动的作用 驱使硬件设备行动 1.2 无操作系统时的设备驱动 典型架构:一个无限循环中夹杂着对设备中断的检测或者对设备的轮询 1.3 有操作系统时的设备...
  • linux 设备驱动开发:基于最新的4.0内核 随书代码 有makefile 可编译调试
  • 1.1. 设备驱动的分类字符驱动驱动网络驱动1.2 硬件基础中央处理器结构的分类:冯诺依曼:指令和数据合并在一起,数据宽度相同(Intel和arm7)哈弗:指令和数据分开,可以有不同的数据宽度(arm9-cortex系列)通用...
  • 设备驱动中使用异步通知可以使得对设备的访问可进行时,由驱动主动通知应用程序进行访问。因此,使用无阻塞I/O的应用程序无需轮询设备是否可访问,而阻塞访问也可以被类似“中断”的异步通知所取代。异步通知类似...
  • 4.1 内核模块程序结构 加载:insmod,modprobe(同时加载模块的依赖模块) 卸载:rmmod 查看已加载的模块及模块间的依赖关系:lsmod,实际上是分析/proc/modules文件 已加载的模块信息放在/sys/module目录下,没加载一...
  • baohua@baohua-VirtualBox:~/develop/linux$ sudo ./module.sh CHK include/config/kernel.release CHK include/generated/uapi/linux/version.h CHK include/generated/utsrelease.h make[1]: `...
  • Linux设备驱动开发详解-基于最新的Linux4.0内核(第三版),包括很多Linux系统驱动的程序代码,应该大多数直接可以调试成功。
  • 1、#/home/baohua/develop/training/kernel 目录 该目录主要是存放了一些驱动程序源码 有四个子目录 1)./drivers 当前目录存放了书中的一些示例驱动代码, 2)./dts-demo 目录 暂未学习到,功能不详 3)./...
  • Linux从未停歇脚步。Linus Torvalds,世界上最伟大的程序员之一,Linux内核的创始人,Git的缔造者,仍然在没日没夜的合并补丁,升级内核。做技术,从来没有终南捷径,拼的就是坐冷板凳的傻劲。 这是一个连阅读都被...
  • 这是第一次印刷的勘误,大部分应该买的都是5刷了,这些错误基本已经绝迹。还是有部分童鞋买的书老书,在找勘误,所以再推送一次。我们欢迎读者给我们发送勘误意见,一经确认,我们将透过某种形式进行表扬和感谢。...
  • [置顶] 《Linux设备驱动开发详解(第3版)》(即《Linux设备驱动开发详解:基于最新的Linux 4.0内核》)进展同步更新 2014-06-30 20:22 阅读(31173) 评论(110)   宋宝华:关于罪与欲望的深渊 - 《人民的...
1 2 3 4 5 ... 20
收藏数 12,867
精华内容 5,146
关键字:

linux设备驱动开发4.0