Linux Driver是什么
导读:本文共7850字符,通常情况下阅读需要26分钟。同时您也可以点击右侧朗读,来听本文内容。按键盘←(左) →(右) 方向键可以翻页。
摘要: Linux Driver即Linux 驱动,linux 系统设计将设备驱动纳入了文件系统,任何一个Linux驱动都需要有一个设备文件,否则应用程序将无法与驱动程序交互。设备分类字符设备块设备网络设备驱动在kernel中的位置linux 系统设计将设备驱动纳入了文件系统, 更为具体的分层调用结构如下所示: Linux Device Modelusb 设备的驱动设备... ...
目录
(为您整理了一些要点),点击可以直达。Linux驱动都需要有一个设备文件,否则应用程序将无法与驱动程序交互。
设备分类
字符设备
块设备
网络设备
驱动在kernel中的位置
linux 系统设计将设备驱动纳入了文件系统,
更为具体的分层调用结构如下所示:
Linux Device Model
usb 设备的驱动设备模型:
设备文件的节点记录的信息:
文件类型
主设备号
次设备号 主设备号和类型决定了驱动的类型及其界面,而次设备号则说明是同类设备中的第几个设备。
devfs 文件系统
在linux 2.4 引入,主要优点:
可以通过程序在设备初始化时在/dev目录下创建设备文件,卸载设备时将它 删除。
设备驱动程序可以指定设备名、所有者和权限位,用户空间程序仍可以修改 所有者和权限位。
不再需要为设备驱动程序分配主设备号以及处理次设备号,在程序中可以直 接给 register_chrdev()传递 0 主设备号以动态获得可用的主设备号,并在 devfs_register()中指定次设备号。
udev 设备文件系统
linux 2.6开始抛弃了devfs,引入了udev 文件系统,基于以下几点:
devfs所做的工作被确信可以在用户态来完成。
一些bug相当长的时间内未被修复。
devfs的维护者和作者停止了对代码的维护工作。
udev 与devfs的区别在于:
devfs 在设备打开时自动加载驱动程序 udev在发现设备时自动加载驱动程序
sysfs 文件系统
udev工作在用户态,利用设备加入或移除时内核所发送的热插拔事件来进行工作,同时hotplug事件,设备的详细信息会由内核输出到位于/sys 的sysfs文件系统。
udev 利用sysfs中的信息来创建设备文件节点等工作
sysfs被看成是与proc、devfs和devpty同 类别的文件系统,该文件系统是一个虚拟的文件系统,它可以产生一个包括所有系统 硬件的层级视图,与提供进程和状态信息的 proc 文件系统十分类似
tree/sys/dev/├──block│├──7:0->../../devices/virtual/block/loop0│├──7:1->../../devices/virtual/block/loop1│├──7:2->../../devices/virtual/block/loop2│├──7:3->../../devices/virtual/block/loop3│├──7:4->../../devices/virtual/block/loop4│├──7:5->../../devices/virtual/block/loop5│├──7:6->../../devices/virtual/block/loop6│├──7:7->../../devices/virtual/block/loop7│├──8:0->../../devices/pci0000:00/0000:00:17.0/ata1/host0/target0:0:0/0:0:0:0/block/sda│├──8:1->../../devices/pci0000:00/0000:00:17.0/ata1/host0/target0:0:0/0:0:0:0/block/sda/sda1│├──8:16->../../devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.2/1-8.2:1.0/host4/target4:0:0/4:0:0:0/block/sdb│├──8:2->../../devices/pci0000:00/0000:00:17.0/ata1/host0/target0:0:0/0:0:0:0/block/sda/sda2│├──8:32->../../devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.2/1-8.2:1.0/host4/target4:0:0/4:0:0:1/block/sdc│├──8:48->../../devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8.2/1-8.2:1.0/host4/target4:0:0/4:0:0:2/block/sdd│├──8:5->../../devices/pci0000:00/0000:00:17.0/ata1/host0/target0:0:0/0:0:0:0/block/sda/sda5│└──8:6->../../devices/pci0000:00/0000:00:17.0/ata1/host0/target0:0:0/0:0:0:0/block/sda/sda6└──char├──10:1->../../devices/virtual/misc/psaux├──10:183->../../devices/virtual/misc/hw_random├──10:184->../../devices/virtual/misc/microcode├──10:200->../../devices/virtual/misc/tun├──10:223->../../devices/virtual/misc/uinput├──10:227->../../devices/virtual/misc/mcelog├──10:228->../../devices/virtual/misc/hpet├──10:229->../../devices/virtual/misc/fuse├──10:231->../../devices/virtual/misc/snapshot├──10:232->../../devices/virtual/misc/kvm12345678910111213141516171819202122232425262728293031
/sys 目录下展示了所有系统中的设备层级目录,其关系大致如下
kobject
linux3.4
structkobject{constchar*name;structlist_headentry;//usedformounttoksetliststructkobject*parent;structkset*kset;structkobj_type*ktype;//指向对象类型描述附指针structsysfs_dirent*sd;//structkrefkref;//引用计数unsignedintstate_initialized:1;unsignedintstate_in_sysfs:1;unsignedintstate_add_uevent_sent:1;unsignedintstate_remove_uevent_sent:1;unsignedintuevent_suppress:1;};123456789101112131415
其中 sysfs_dirent,
/**sysfs_dirent-thebuildingblockofsysfshierarchy.Eachand*everysysfsnodeisrepresentedbysinglesysfs_dirent.**Aslongass_countreferenceisheld,thesysfs_direntitselfis*accessible.Dereferencings_elemoranyotherouterentity*requiress_activereference.*/structsysfs_dirent{atomic_ts_count;atomic_ts_active;#ifdefCONFIG_DEBUG_LOCK_ALLOCstructlockdep_mapdep_map;#endifstructsysfs_dirent*s_parent;constchar*s_name;structrb_nodes_rb;union{structcompletion*completion;structsysfs_dirent*removed_list;}u;constvoid*s_ns;/*namespacetag*/unsignedints_hash;/*ns+namehash*/union{structsysfs_elem_dirs_dir;structsysfs_elem_symlinks_symlink;structsysfs_elem_attrs_attr;structsysfs_elem_bin_attrs_bin_attr;};unsignedshorts_flags;umode_ts_mode;unsignedints_ino;structsysfs_inode_attrs*s_iattr;};123456789101112131415161718192021222324252627282930313233343536373839
kset
structkset{structlist_headlist;//doublelistheadspinlock_tlist_lock;structkobjectkobj;//嵌入的kobjectconststructkset_uevent_ops*uevent_ops;//事件操作集};123456
其中 kset_uevent_ops 定义了kset的对所包含的kobject 可以执行的操作,包括事件过滤和导出环境变量操作。
structkset_uevent_ops{int(*constfilter)(structkset*kset,structkobject*kobj);//事件过滤constchar*(*constname)(structkset*kset,structkobject*kobj);int(*constuevent)(structkset*kset,structkobject*kobj,structkobj_uevent_env*env);//环境变量导出};1234567
device
device 数据结构用于描述设备相关的信息和设备之间的层次关系,设备与总线与驱动之间的关系。
structdevice{structdevice*parent;structdevice_private*p;structkobjectkobj;constchar*init_name;/*initialnameofthedevice*/conststructdevice_type*type;structmutexmutex;/*mutextosynchronizecallsto*itsdriver.*/structbus_type*bus;/*typeofbusdeviceison*/structdevice_driver*driver;/*whichdriverhasallocatedthisdevice*/void*platform_data;/*Platformspecificdata,devicecoredoesn'ttouchit*/structdev_pm_infopower;structdev_pm_domain*pm_domain;#ifdefCONFIG_NUMAintnuma_node;/*NUMAnodethisdeviceiscloseto*/#endifu64*dma_mask;/*dmamask(ifdma'abledevice)*/u64coherent_dma_mask;/*Likedma_mask,butforalloc_coherentmappingsasnotallhardwaresupports64bitaddressesforconsistentallocationssuchdescriptors.*/structdevice_dma_parameters*dma_parms;structlist_headdma_pools;/*dmapools(ifdma'ble)*/structdma_coherent_mem*dma_mem;/*internalforcoherentmemoverride*/#ifdefCONFIG_CMAstructcma*cma_area;/*contiguousmemoryareafordmaallocations*/#endif/*archspecificadditions*/structdev_archdataarchdata;structdevice_node*of_node;/*associateddevicetreenode*/dev_tdevt;/*dev_t,createsthesysfs"dev"*/u32id;/*deviceinstance*/spinlock_tdevres_lock;structlist_headdevres_head;structklist_nodeknode_class;structclass*class;conststructattribute_group**groups;/*optionalgroups*/void(*release)(structdevice*dev);};12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
操作device的相关函数:
device_register():/sys/devices下创建相关目录device_unregister():移除相关目录get_device:增加引用计数put_device:减小引用计数1234
device_driver
structdevice_driver{constchar*name;structbus_type*bus;structmodule*owner;constchar*mod_name;/*usedforbuilt-inmodules*/boolsuppress_bind_attrs;/*disablesbind/unbindviasysfs*/conststructof_device_id*of_match_table;int(*probe)(structdevice*dev);int(*remove)(structdevice*dev);void(*shutdown)(structdevice*dev);int(*suspend)(structdevice*dev,pm_message_tstate);int(*resume)(structdevice*dev);conststructattribute_group**groups;conststructdev_pm_ops*pm;structdriver_private*p;};12345678910111213141516171819202122
其中
structbus_type{constchar*name;constchar*dev_name;structdevice*dev_root;structbus_attribute*bus_attrs;structdevice_attribute*dev_attrs;structdriver_attribute*drv_attrs;int(*match)(structdevice*dev,structdevice_driver*drv);int(*uevent)(structdevice*dev,structkobj_uevent_env*env);int(*probe)(structdevice*dev);int(*remove)(structdevice*dev);void(*shutdown)(structdevice*dev);int(*suspend)(structdevice*dev,pm_message_tstate);int(*resume)(structdevice*dev);conststructdev_pm_ops*pm;structiommu_ops*iommu_ops;structsubsys_private*p;};1234567891011121314151617181920212223
Kernel modules
模块安装与卸载
并不是所有的module都是在编译内核时加入的,主要有以下考虑:
所有模块默认编译进内核,将使得内核臃肿
使得内核不易进行扩展
linux提供可动态安装模块的机制,可将模块编译成ko文件,推迟链接的时间:
在需要时通过insmod 完成链接过程,链接系统内核导出符号,完成模块的可插拔功能。
相对应的,移除模块通过rmmod完成
考虑到模块之间可相互依赖,进行调用,因此在载入模块的同时需要检查依赖的模块是否已经载入,modprobe 可以自动加载依赖模块,其根据依赖信息工作:depmod -A 可生成新模块的依赖信息 推荐使用modprobe 进行模块安装与卸载:
modprobemodule[parameter]modprobe-rmodules;如果依赖的模块有被其他模块调用,则不会移除,反之,一并移除12
导出符号表
模块之间可通过到处符号表实现依赖关系
EXPORT_SYMBOL(function_name) 导出函数符号 EXPORT_SYMBOL_GPL(function_name) 导出给符合GPL 协议的模块使用
The minor number is used by the kernel to determine exactly which device is being referred to. Depending on how your driver is written (as we will see below), you can either get a direct pointer to your device from the kernel, or you can use the minor number yourself as an index into a local array of devices. Either way, the kernel itself knows almost nothing about minor numbers beyond the fact that they refer to devices implemented by your driver.
Module Stack
驱动常见错误debug
invalid format
#insmodhello.koErrorinserting'./hello.ko':-1Invalidmoduleformat12
cat /var/log/messages
</div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
Linux Driver是什么的详细内容,希望对您有所帮助,信息来源于网络。