别人的开发驱动经验(转载)

minifilter开发文件过滤驱动、以及syser调试的经验 minifilter开发文件过滤驱动、以及syser调试的经验。  刚刚完成一个产品的开发,用了两个月,真不容易,像我这种菜鸟,为了搞清一个常识,得从老谭的那本古董级C程序设计翻起。  首先说驱动教程。 楚狂人谭文的《寒江独钓-Windows内核安全编程》和张帆的《Windows驱动开发技术详解》要反复地读。  我用的是最新的WDK 7600,那个帮助真叫人汗,英文的倒罢了,怎 阅读详情
开发驱动程序的过程


编写内核模式的代码于应用程序的代码是不同的,因为驱动程序是操作系统的信任的部分。它的代码必须遵循特殊的规则,小心的编写。
驱动程序开发策略

  像大多数的软件,驱动程序也使用有组织的开发方法。这个部分将介绍一些技巧来尽量减少开发时间。

使用规范的开发方法

  一般的,如果编写一个设备驱动程序没有一个开发策略。而是去匆忙的测试全新的硬件,往往测试代码会成为驱动程序的主要部分。也许设备驱动程序是被一些对操作系统不熟悉的程序员编写的,第一个驱动程序的编写会是一个驱动程序作者全面了解系统构架的旅程。

  幸运的是,疯狂的软件编写的日子过去了。在复杂的硬件和操作系统的环境下,想怎么编写就怎么编写的代码是不会运行的。

下面是一个简短的开发技术(它们中的一些是来自实时设计技术)列表。

1. 数据流图可以将一个驱动程序分成独立的功能部分。通过这个图可以容易的看出各个部分的联系,和数据的流向。

2. 状态机模型是一个描述驱动过程控制流的好的方法,特别是管理复杂的硬件和软件协议的驱动程序。在验证状态机的过程中,可能发现驱动程序中的同步问题。

3. 分析期待的数据的重复率或者输入输出的响应将得到一系列定量的时序条件。对于确定驱动程序的总性能是非常重要的。

4. 另一个有用的工具是外部事件和驱动程序响应动作的列表。这个列表应该包括设备的硬件事件和用户通过I/O管理器的软件事件。

使用这些技术分解一个驱动程序成为一个个定义好的功能部分。有时,这些意味着分解一个简单的,单片的驱动程序成为一些硬件相关的端口驱动程序和硬件无关的类驱动程序。在任何时候,在工程的开始,分析一个驱动程序的设计所花费的时间多于设计工程它自己,这样可以减少调试和维护的时间。

使用渐进的开发方法

 一旦最初的分析和设计完成,就要开始编写代码了。按照以下的步骤进行可以减少调试的时间:

1. 确定驱动程序需要哪些内核模式对象。

2. 确定驱动程序需要哪些上下文环境或者状态信息和这些信息的存储位置。

3.首先编写DriverEntry和Unload例程,最初不要增加即插即用支持,这样允许通过控制面板手动的测试驱动程序的装载和卸载。

4. 添加处理IRP_MJ_CREATE和IRP_MJ_CLOSE的操作和一些不需要进行设备访问的例程。然后可以使用一个简单的WIN32程序调用CreateFile和CloseHandle来测试。

5. 添加寻找和分配驱动程序的硬件的代码,还有在驱动程序被卸载后的重新分配硬件的代码。如果硬件支持即插即用,这一步测试硬件和驱动程序的自动加载能力。

6. 添加处理IRP_MJ_XXX函数的派遣例程,最初的例程应该没有使用物理设备,后来新的代码应该使用简单的WIN32程序进行测试,例如ReadFile和WriteFile调用,或者其它支持的函数。

7. 最后完成Start I/O例程,ISR和DPC例程。现在可以使用真实的数据和硬件进行测试。

一个有用的提示: 当硬件的确切行为是不能肯定的时候,增加一个DeviceIoControl函数,这个例程直接访问设备的寄存器,这时可用一个简单的WIN32程序直接控制设备寄存器。记得在发布最后的驱动程序版本的时候删除这个功能。

使用驱动程序实例

Windows 2000驱动程序开发包(DDK)里面有相当多的驱动程序实例。有许多方法使用者些代码来使驱动程序的开发变的更容易,微软鼓励从这些代码实例中剪切和粘贴。

编码技术与习惯

  编写一个信任的内核模式部分和编写应用程序是不同的。下面提供一些编码技术与习惯,使编写代码更加容易一些。

一般性的建议

首先,在编写驱动程序的时候应当遵循一些一般性的指导方针:

1. 尽量避免使用汇编语言。因为它使代码难于阅读,没有移植性,维护困难。HAL宏提供一个安全的机制去访问I/O设备寄存器。因此,在驱动程序中极少使用汇编语言。

2. 对于特定平台的代码,提供一个单独的模块,至少要用#ifdef/#endif语句将它们括起来。

3. 不要使用标准的C运行时库连接驱动程序。它除了浪费存储器空间之外,一些库的例程的状态或者上下文环境不是线程安全或者驱动程序安全的方式。

4. 这一条可能不适合编写设备驱动程序。天天使用运行库环境的C语言程序员,常常不清楚C程序和C运行库的差别。C运行库需要初始化,它尝试初始化一个堆区域和调用全局对象的构造器(使用C++时)。所有的这些任务防碍驱动程序的操作。

5. Windows 2000提供它自己的环境支持内核模式代码。包括RtlXxx函数(运行库)等多个公用的C语言运行库服务支持。

6. 用某种源代码控制管理驱动程序工程。微软的Visual Source Safe是一个好的选择。对于大的跨平台的工程Rational公司的ClearCase也值得考虑。WinMerge也是必备。

命名规范

  所有的大的软件工程应该为例程和变量定义制定一些标准的命名规范,设备驱动程序也不例外。好的命名规范提高开发,调试,除错和维护的效率。

  微软为DDK提供一个命名规范,NTDDK.H定义所有的数据类型,结构,常数,宏。按照DDK规范,所有这些类型的名字都是大写的。甚至是C语言数据类型也提供一个相应的DDK名字。例如,C语言的数据类型void*在NTDDK.H中是PVOID。这些定义可以很容易的扩展到未来的64Bits的平台。

微软推荐将每个驱动程序例程的名字加上一个特殊的前缀。例如,编写一个鼠标类驱动程序,Start I/O例程的名字可能是MouseClassStartIo。同样的缩写成为两个或者三个字符通常用在内部数据的命名。这样一个例程的名字可能是MouConfiguration。

头文件

  除了包含NTDDK.h或者WDM.h,一个驱动程序应当使用私有的头文件去隐藏硬件和平台依赖的变量。例如,寄存器访问宏应该存储在一个私有的头文件,这些宏应该被#ifdef包括。这个技术解决在不同的I/O空间和存储器空间访问寄存器的问题。

甚至可解决移植性,寄存器访问宏使驱动程序容易阅读和维护。下列代码片段是一个并行端口设备访问的宏,这个实例假定驱动程序的一些初始化代码已经把第一个设备寄存器的地址放到设备Extension的 PortBase中。

// 定义设备计存器为偏移地址

#define PAR_DATA 0

#define PAR_STATUS 1

#define PAR_CONTROL 2

//为寄存器定义访问宏,每个宏使用指向设备Extension的指针作为参数

#deinfe ParWriteData( pDevExt, bData ) \

(WRITE_PORT_UCHAR( pDevExt->PortBase + PAR_DATA, bData ) )

#define ParReadStatus( pDevExt ) \

(READ_PORT_UCHAR( pDevExt->>PortBase + PAR_STATUS ))

#define ParWriteControl( pDevExt, bData ) \

(WRITE_PORT_UCHAR( pDevExt->PortBase + PAR_CONTROL, bData ) )

状态返回值

  WIN2000的内核模式部分使用32Bits的状态值去描述一个特殊操作的结果。这些代码的数据类型是NTSTATUS,在三种情况下使用这个状态代码。

  1. 使用任何WIN2000内部函数的时候,NTSTATUS值汇报调用成功或者失败。

  2. I/O管理器调用一个驱动程序支持的回调例程,例程通常返回一个NTSTATUS值给系统。

  3. 在完成I/O请求的处理之后,驱动程序必须用一个NTSTATUS值标记IRP,这个值最终被映 射到一个Win32 ERROR_XXX代码。NTSTATUS代码于Win32 error代码不是同一回事。I/O管理器提供它两个之间的映 射。DDK的帮助描述它们的映 射关系,它值得一读。

NTSTATUS.h中描述大量的NTSTATUS值的符号名。所有的这些名字是STATUS_XXX的形式,XXX描述真正的状态信息。STATUS_SUCCESS,STATUS_NAME_EXISTS都是这些名字的实例。

当一个系统例程返回一个NTSTATUS值,DDK头文件提供一个方便的宏去测试调用的成功于失败信息。下面的代码片段解释了这个技术:

NTSTATUS status;

:

status = IoCreateDevice ( ... );

if ( !NT_SUCCESS( status )) { // 产生错误,清除和退出

: }

  一定要检查系统例程调用的返回值,否则错误将传送给驱动程序代码的其它部分,也可能是系统代码。尽早的捕捉到错误是软件工程师的主要的规则。





Windows 2000驱动程序支持的例程

I/O管理器和WIN2000其它的内核模式部分提供大量的供驱动程序调用的函数。DDK文文件描述了这些函数。现在,指出WIN2000支持的例程种类已经足够。如表5.1所示:

分类
支持
函数名

Executive
存储器分配,互锁队列区域,监控列表,系统工作者线程
ExXxx()

HAL
设备寄存器,总线访问
HalXxx()

I/O Manager
普通驱动程序支持
IoXxx()

Kernel
DPC,同步
KeXxx()

Memory Manager
虚拟存储器到物理存储器的映 射,存储器分配
MmXxx()

Object Manager
句柄管理
ObXxx()

Process Manager
系统线程管理
PsXxx()

Runtime library
字符串操作,大整数运算,寄存器访问,安全性函数,时间和日期函数,队列和列表支持
RtlXxx() (大部分的例程)

Security Monitor
特权检查,安全描述符函数
SeXxx()

(Miscellaneous)
内部系统服务
ZwXxx()


表5.1WIN2000支持的例程种类

  ZwXxx函数需要更多的说明。它们实际上是为所有的NtXxx用户模式系统服务的内部调用接口。用户模式和内核模式接口时不同的,ZwXxx函数不执行任何参数校验。虽然这样的函数有很多,DDK文件仅仅描述很少一部分。使用无正式文件的函数是一个冒险,因为微软在未来可能改变或者删除这些函数。

  I/O管理器提供几个方便的函数,它们包装了一个或者多个对其它内核模块的低级的调用,应该尽量使用它们。

丢弃初始化例程

  一些编译器支持声明某些函数函数可以丢弃的选项。被选中的函数在驱动程序完成加载后被移出存储器,这样使驱动程序更小。最好使用这种开发环境。

可以丢弃的函数是DriverEntry和那些只是被DriverEntry调用的子程序。以下的代码片段描写怎样利用可以丢弃的代码(使用微软的C程序开发环境):

#ifdef ALLOC_PRAGMA

#pragma alloc_text( init, DriverEntry )

#pragma alloc_text( init, FuncCalledByDriverEntry )

#pragma alloc_text( init, OtherFuncCalledByDriverEntry )

:

#endif

alloc_text pragma必须出现在函数名声明之后,定义之前。在pragma声明中的函数必须在同一个编辑单元。

控制驱动程序分页

  没分页的系统存储器是宝贵的资源。驱动程序可以定义适当的例程到分页的存储器来减少非分页存储器的负担,任何IRQL是PASSIVE_LEVEL的函数可以在分页的存储器中运行,包括Reinitialize例程,Unload例程,Shutdown例程,Dispatch例程,线程函数以及任何运行在PASSIVE_LEVEL IRQL的帮助函数。再一次,是alloc_text pragma执行这个声明,例子如下:

#ifdef ALLOC_PRAGMA

#pragma alloc_text( page, Unload )

#pragma alloc_text( page, Shutdown )

#pragma alloc_text( page, DispatchRead )

#pragma alloc_text( page, DispatchHelper )

:

#endif

最后,如果整个驱动程序很少使用,它可以被暂时的被翻出存储器。MmPageEntireDriver例程不管驱动程序声明的存储器管理属性,就将整个模块暂时的翻页。这个函数应该在DriverEntry例程的末尾调用和当不再打开任何它的设备句柄时从IRP_MJ_CLOSE的派遣例程,当使用这个驱动程序的时候,就在IRP_MJ_CREATE的派遣例程中调用MmResetDriverPaging来使驱动程序的页属性恢复正常。

当使用者个技术的时候,注意两件事:

1. 调用MmPageEntireDriver时,确定没有IRP被驱动程序的高级IRQL部分处理。

2. 当ISR被分页的时候,确定没有设备中断到达。

驱动器存储器分配

  程序设计涉及的一个重大的方面是分配存储单元。不幸的是,驱动程序不能简单的调用malloc和 free,或者new和delete。要确定分配正确类型的存储器,使用完毕后必须释放分配的存储器,因为内核模式代码没有自动清除机制。

驱动程序可用的存储器

  驱动程序有三种分配存储器的选择。标准的分配存储器的选择依靠持续时间,大小,IRQL来确定。可用的选择是:

1. 内核堆栈:内核模式堆栈在驱动程序例程执行期间给局部变量提供有限数量的非分页存储空间。

2. 分页池: 运行在DISPATCH_LEVEL IRQL以下的例程可以有一个称作分页池的堆。这个区域的存储器是可分页的,当它访问的时候可能产生缺页故障。

3. 非分页池:运行在提高IRQL的例程需要从一个称作非分页池的堆空间中分配暂时的存储空间。系统保证非分页池中的虚空间总是在物理存储器空间中。I/O管理器创建的设备和控制器Extension就存储在这个区域。

因为驱动程序必须是可重入的,所以除了只读数据之外从不分配全局变量。否则,一个线程尝试存储数据到的全局变量,与另一个线程的读写将可能是同一个数据。

当然,驱动程序的局部静态变量同样糟糕。驱动程序的状态信息必须存储在其它的地方,例如像以前介绍的设备Extension。

使用内核堆栈

  在80X86的平台上,内核堆栈的大小仅仅是12Kbyte,在其它的平台上,内核堆栈的大小是16Kbyte。因此,内核堆栈是宝贵的资源,内核堆栈溢出将导致异常。遵循以下指导方针可以避免内核堆栈溢出:

1. 不要设计有很深的嵌套的内部例程,保持调用树尽量平坦。

2. 应尽量避免递归,必须的时候应当限制递归的深度。驱动程序不是进行Fibonacci级数运算的地方。

3. 不要使用内核栈来创建大的数据结构,大的数据结构应该在堆中创建。

另一个内核堆栈的特性是它存在于高速缓冲存储器中,所以它不能用作DMA操作,DMA的缓冲区应该在非分页池中。

使用缓冲池

  使用内核例程ExAllocatePool和ExFreePool在缓冲池中分配存储空间。

  这些函数允许分配下列存储空间:

1. NonPagedPool:IRQL高于或者等于DISPATCH_LEVEL的驱动程序例程可用的存储器。

2. NonPagedPoolMustSucceed:驱动程序继续操作的重要的临时存储空间。在紧急的情况下使用这种存储空间,使用后要尽快释放。实际上,如果分配失败将会产生异常。

3. NonPagedPoolCacheAligned:保证CPU高速缓存线的自然边界对齐的存储器,驱动程序使用这中存储器作为永久的I/O缓冲区。

4. NonPagedPoolCacheAlignedMustS:对驱动程序重要的操作的临时缓冲区。末尾的S表示成功。像之前的MustSucceed操作这个请求大概从没有被使用过。

5. PagedPool: 有被IRQL低于DISPATCH_LEVEL的例程使用。通常,这些包括驱动程序的初始化,清除,派遣例程和任何内核模式的线程。

6. PagedPoolCacheAligned:它是文件系统使用的I/O缓冲区存储空间,

使用系统存储器的时候,记得下列几点:

1. 缓冲池是珍贵的系统资源,不要太奢侈,尤其是非分页区域。

2. 当分配或者释放非分页存储器驱动程序必须在或者高于DISPATCH_LEVEL的IRQL上执行。驱动程序必须执行在或者低于below APC_LEVEL的IRQL上分配或者释放分页存储器。

3. 尽快释放不再使用的存储器,否则系统在缺少存储器的情况下运行效率会变低。特别的,要确认在卸载驱动程序的时候归还空间给缓冲池。

存储器再分配

  一般地,驱动程序应当避免常常分配和释放小于PAGE_SIZE bytes的缓冲池,这样使缓冲池中产生碎片而不能被其它内核模式代码使用。如果必须这样的话,就分配一个大块的存储区域和提供一个再分配子程序去分配它们。

实际上,一个C程序员可能编写自己的在一个大的缓冲池中分配和释放存储空间的子程序,一个C++程序员可能重载new和delete操作。

一些驱动程序需要管理一些小的固定尺寸的存储块。例如,SCSI驱动程序必须提供一个SCSI请求块(SRBs),它被用来发送命令给SCSI设备。



内核提供两个不同的处理在分配的机制:

区域缓冲区

  区域缓冲区是一块驱动程序分配的缓冲池。Executive例程提供管理分页或者非分页存储器中的固定尺寸的存储块。

使用区域缓冲区时要注意同步,特别的,如果一个中断服务,DPC,派遣例程都需要访问统一个区域缓冲区,这时要使用一个Executive自旋锁来同步。如果所有的访问操作在统一个IRQL水平,可以使用一个互斥体代替。

在安装区域缓冲区之前,必须了解ZONE_HEADER数据结构。区域缓冲区或者快速互斥体对象必须声明和初始化。下面是管理区域缓冲区的步骤:

1. 调用ExAllocatePool请求区域缓冲区,然后使用ExInitializeZone初始化它,这个步骤常常在DriverEntry例程中执行。

2. 调用ExAllocateFromZone或者ExInterlockedAllocateFromZone从区域缓冲区分配一个块,后者使用一个自旋锁去同步访问区域缓冲区。前者的同步工作留给了驱动程序代码。

3. 调用ExFreeToZone或者InterlockedFreeToZone释放分配的块。

4. 在驱动程序的Unload例程,使用ExFreePool释放整个区域缓冲区的存储空间。在释放区域缓冲区的时候,必须确定区域缓冲区中的块都被释放。

一个区域缓冲区应该不大于必要的空间,MmQuerySystemSize可以得到可用的系统存储空间的总数,另一个Executive函数MmIsThisAnNTAsSystem是用来检查当前的平台是否是WIN2000的服务器版本,运行在服务器版本的驱动程序可以分配稍微大一点的空间。

如果在区域缓冲区中分配存储块失败,驱动程序将使用标准的缓冲池去得到请求的块,这个策略需要一个清楚的结构去指出分配是来自区域缓冲区还是缓冲池。这样才能调用合适的例程释放这个块。

通过ExExtendZone或者ExInterlockedExtendZone可以使存在的区域缓冲区的更大,但是这些函数很少被使用,系统好象不能正确的分配额外的区域缓冲区,实际上,微软有考虑过废除整个区域缓冲区的抽象。WIN2000提供一个更加有效的监视列表构架。

监视列表

  监视列表(Lookaside List)是一个固定尺寸存储块的一个连接列表,不像区域缓冲区,根据系统状态的不同监视列表可以动态的增大或者减小。因此合适大小的监视列表可能较少的浪废存储空间。

与区域缓冲区相比,在监视列表上使用同步机制更加有效,如果CPU构建中有一个8-byte比较交换指令,Executive使用它去使访问监视列表的操作连续。在没有这个指令的平台上,对于非分页池就使用一个自旋锁,对于分页池就使用一个互斥体。

在使用监视列表之前,必须声明一个NPAGED_LOOKASIDE_LIST或者PAGED_LOOKASIDE_LIST(依赖于存储空间是否分页)结构,下面介绍监视列表的管理过程:

1. 使用ExInitializeNPagedLookasideList或者ExInitializePagedLookasideList函数初始化列表的头结构,通常DriverEntry或者AddDevice例程执行这个任务。

2. 调用ExAllocateNPagedLookasideList或者ExAllocatePagedLookasideList从监控列表分配一个块,可以在驱动程序的任何地方调用这两个例程。

3. 调用ExFreeToNPageLookasideList或者ExFreeToPageLookasideList释放块。

4. 调用ExDeleteNPagedLookasideList或者ExDeletePagedLookasideList释放任何于监控列表相关联的资源,这个函数通常在驱动程序的Unload或者RemoveDevice例程中执行。

监控列表初始化函数简单的设置列表头,它们不实际的分配存储器给列表。初始化函数请求列表可以拥有的最大数量(称作列表的深度)的块。

当使用分配函数的时候,系统才分配需要数量的存储空间,当块被释放,他们被添加到监控列表,直到最大允许深度。任何块的释放将导致存储空间被释放到系统,这样一段时间之后,在监控列表中的块数量将趋近于列表深度附近。

要小心控制监控列表的深度,如果太浅,系统会常常执行昂贵的分配和释放的动作,如果太深,会造成存储空间的浪费。列表头结构的统计数字可以帮助决定列表深度。
[转载]基于PDIUSBD12的USB通讯开发的一些经验  基于PDIUSBD12的USB通讯开发的一些经验 去年暑假的时候,由于种种原因没有回家,老板又没交代什么事做,因此有点无聊。恰巧实验室里师兄有块周立功的DP51实验板,里面有基于PDIUSBD12的USB模块,于是借来学习。经过两个月左右的时间,总算顺利实现单片机与PC的USB通讯。下面简单谈一下自己在学习过程中的一些想法,错误之处还请指教。在做USB开发前应该了解整个开发过程总体需要做些什么工 阅读详情

相关推荐

触摸屏驱动开发——转载

触摸屏驱动开发——转载

qq_44884287的博客 1319

驱动开发经验

驱动开发首先确定驱动框架(声明出入口,注册设备,创建设备节点、初始化硬件信息、),主要对要操作的设备地址进行查找,各种通信协议,设备树中没有的需要自己将设备信息添加至设备树。

qq_45561012的博客 720

BDD行为驱动开发测试Cucumber经验分享

自动化测试, Cucumber, BDD

宣兆鹏Robin的专栏 9074

day2 驱动开发 c语言

这样写会造成无法处理内核页面请求的虚拟地址内部错误,没找到解决方法。

weixin_66726984的博客 812

驱动开发经验集锦

驱动开发经验集锦驱动开发经验集锦

涨姿势|小众建模软件Make human,MakeClothes插件使用详解教程(2)

衣服可以从头开始建模,或者通过改变人体网格或由MakeClothes工具提供的“服装助手”(见下文)来建模。在设计和建模一件衣物时,应该记住两个限制。首先,将服装网格映射到人体网格的算法要求服装网格完全由四面体组成。其次,知道MakeClothes每件衣服只支持一种材料是很重要的。 完成MakeClothes工作流程后,您的HOME / makehuman / v1 / data / clothes中的工具将创建一个新文件夹。该文件夹将采用用户为服装项目提供的唯一名称。该文件夹将填充必要的资源,以使该项目在

Crazy_in_3Dmax的博客 1874

C语言驱动编程详细解析(超多代码案例)

数据压倒一切。如果选择了正确的数据结构并把一切组织的井井有条,正确的算法就不言自明。编程的核心是数据结构,而不是算法。——Rob Pike。

m0_61687959的博客 1985

D触发器(D Flip-Flop)与D锁存器(D Latch)

在解释这个练习题之前,我们先来简单回顾一下D触发器(D flip-flop)和D锁存器(D latch)的概念,以及它们在数字电路中的作用。这将帮助我们理解所提到的练习。

weixin_65190179的博客 9165

从Linux小白到驱动开发者:为什么我必须在驱动中使用private_data

基于我的经验,我总结出了使用总是在open函数中设置private_data在其他操作函数中通过private_data获取设备信息配合适当的锁机制保护共享数据为多设备实例设计合适的数据结构在release函数中清理资源从最初的困惑到现在的熟练运用,机制让我深刻理解了Linux内核设计的精妙之处。它不仅仅是技术实现,更是一种设计哲学的体现。希望我的经验能够帮助更多开发者理解并正确使用这个重要的机制。记住:好的驱动代码,从正确使用private_data开始!

niuTyler的博客 258

Camera | 瑞芯微rk3568平台MIPI-CSI驱动:从设备树到V4L2框架的完整链路解析

本文深入解析瑞芯微rk3568平台MIPI-CSI驱动的完整链路,从设备树配置到V4L2框架集成。详细介绍了rk3568的MIPI-CSI驱动架构、设备树关键节点布局、驱动初始化流程及数据流路径,帮助开发者快速掌握摄像头控制器的调试与优化技巧,实现稳定的视频采集系统。

weixin_28703489的博客 290

Claude Skills 深度讲解

阶段 1:Function Call(2023)├─ 大模型可以调用外部工具├─ 问题:缺乏对任务的深度理解└─ 局限:工具调用简单线性阶段 2:MCP 上下文工程(2024)├─ 大模型有了更丰富的上下文和工具├─ 问题:仍然需要手动编写复杂的 Prompt└─ 局限:每次对话都需要重新加载上下文阶段 3:Claude Skills(2025)├─ 大模型有了「能力模块」的概念├─ 可以动态加载、组合、执行专门的工作流├─ 真正实现了「知识的模块化和复用」

u013134676的博客 1464

零基础小白如何自学软件驱动开发

自学驱动开发需要扎实的编程基础、操作系统原理、硬件知识和调试技能。通过逐步学习C语言、操作系统原理、Linux内核、硬件接口以及驱动程序的开发,你可以系统地掌握驱动开发技术。最重要的是通过大量的实践和调试,不断提升自己的开发能力。同时,参与开源项目和技术社区,也能帮助你在实践中不断进步。

小宝哥Code的专栏 2176

NLP高频面试题(三十一)——多模态预训练模型的主要结构、特征对齐与融合方法及对比损失函数详解

多模态预训练模型通过创新的架构设计和训练策略,在跨模态理解和表示学习上取得了显著进展。从单塔到双塔,从编码器-解码器混合到图结构模型,研究者们探索了不同的模态融合途径;配合显式与隐式对齐手段以及有效的对比学习损失,当前的多模态模型已经能够在图文检索、视觉问答、图像描述生成等任务上接近甚至超越专门的有监督模型。可以说,多模态预训练成为了继NLP和CV单模态预训练之后的又一个AI热点领域。模型规模与泛化:与单模态的大型预训练模型类似,多模态模型的参数规模和训练数据规模在迅速增长。

WeLearnNLP 2924

WinCE USB驱动开发经验谈(转载)

随着USB2.0设备的不断增加,USB设备驱动开发在嵌入式开发中变的越来越重要。Windows CE支持USB 2.0更是对这一波新技术浪潮产生巨大的推动。本文的作者分析了自己进行USE驱动开发的经历,希望可以让读者少走一些弯路。 随着USB2.0设备的不断增加,USB设备驱动开发在嵌入式开发中变的越来越重要。Windows CE支持USB 2.0更是对这一波新技术浪潮产生巨大...

aotingyou8613的博客 221

提示工程架构师揭秘:prompt优化中的“隐性成本”如何控制?

当我们谈论Prompt优化时,往往聚焦于“效果提升”——比如让模型生成更准确的回答、更符合要求的格式。优化的本质是“成本-收益”的平衡。那些看不见的“隐性成本”,比如反复调试的时间消耗、复杂Prompt带来的认知负荷、长文本导致的系统资源浪费、后续维护的无穷麻烦,往往会在长期运营中成为压垮效率的“稻草”。本文将从提示工程架构师的视角,揭秘Prompt优化中的“隐性成本”到底是什么、如何量化,以及通过哪些工程化手段将这些“看不见的消耗”转化为“可控制的效率”。

操作系统内核探秘的博客 700

医疗AI知识库更新慢?提示工程架构师用Agentic AI自动更新的策略

我们的目标是用Agentic AI替代传统更新流程中的“重复劳动”,让医疗知识库(以知识图谱为例)能自动跟踪最新医学进展,把“更新周期从数月缩短到数天”。从PubMed/指南数据库自动抓取新文献;用提示工程从文本中提取结构化医学知识;自动校验新知识与旧知识的冲突;将通过校验的知识写入知识图谱。拆问题:先讲医疗知识库更新慢的3大根源;给方案:用Agentic AI设计4个“小助手”解决问题;讲原理:每个小助手的工作逻辑+提示工程技巧;做实战。

AI 原生应用开发的博客 1061

呜呜....可惜...呜呜,也谈谈测试驱动开发

  没有参加本周星期五晚上的活动,可惜了,下次一定要叫上我呀。   做人要厚道,你怎么那么不厚道,居然没有叫上我, Allen Lee,你也是... Idior,不要笑,你也不是好人... 虽然接触不久,但根据实际的经验,我也谈谈测试驱动开发,希望能够抛砖引玉 转载于:https://www.cnblogs.com/Willi...

weixin_34175509的博客 81

记录Android Studio连接华为(nova)手机鸿蒙系统踩过的坑

鸿蒙系统的华为老机子比较麻烦,坑有点多,兄弟们加油!

沉迷单车的追风少年 7922

MDSF:SoftFluent敏捷模型驱动开发介绍

    模型驱动软件工厂的概念现在在软件行业越来越多了,OpenExpressApp的目标也是做一个类似的东东,本篇给大家介绍另一个模型驱动软件工厂的应用平台SoftFluent。 软件开发的挑战 常用方法      失败原因 技术缺乏 经验缺少 框架过渡设计 成功方程式模型 SoftFluent原则 So...

weixin_33800593的博客 111

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

转载:驱动SYS开发总结

目录1.驱动简介1.1.驱动是什么1.2.sys文件1.3.inf文件1.4.usb-client driver2.WDM机制2.1.WDM驱动的分层机制2.2.PDO以及IRP机制2.3.WDM驱动程序code构成2.4.必需的处理3.USB类驱动接口3.1.USB类驱动和URB3.2.URB详细3.3.常用函数4.我们的设备5.SYS开发5.1.安装配置开发环境5.2.制作inf文件5.3.编

bbdg的专栏 1381

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

学习驱动的一些经验2

天嵌上转载的: 别人学习驱动的一些经验,先保存在这里。 学了这么久,看了很多资料。发现大部分资料都是告诉你是什么?为什么?和学什么。却没告诉你怎么学。所以我在门外徘徊了很久,至今,看了韦老师的视频,才有所领悟。虽然仍是菜鸟一枚,但是却想将这些感想和大家分享。求高人指正,也为同在郁闷迷茫期的通道门提供一些参考。 我以为,LDD这东西,能站的上边儿的知识有三块: 1

KevinTq的专栏 1150

如何在Linux上安装最新NVIDIA驱动-转载-跳坑经验

title: 如何在Linux上安装最新NVIDIA驱动–转载+跳坑经验 copyright: true tags: ubuntu abbrlink: 18e77cfa date: 2019-01-03 20:24:43 好久没更blog了,在忙一些项目啥的,之前从Ubuntu16.04更新到Ubuntu18.04,N卡驱动掉了…费尽心思安好了。这次gnome出问题了,卸载gnome重装后发现n...

tsvico的博客 1万+

(转载)Windows文件系统过滤驱动开发教程

0.       作者,楚狂人自述我长期网上为各位项目经理充当“技术实现者”的角色。我感觉Windows文件系统驱动的开发能找到的资料比较少。为了让技术经验不至于遗忘和引起大家交流的兴趣我以我的工作经验撰写本教程。我的理解未必正确,有错误的地方望多多指教。有问题欢迎与我联系。我们也乐于接受各种驱动项目的开发。邮箱为MFC_Tan_Wen@163.com,QQ为16191935。对于这本教程,您可以

峥嵘岁月 1万+
上一篇: 利用PDB文件获取未导出全局变量、函数等信息
下一篇: 基于x86-64架构的汇编资料收集
OSReact
博客等级 码龄14年 34粉丝 47原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值