一)驱动注册open函数都干了些什么?register_chrdev-cdev_add-kobj_mapfile:fs/char_dev.cintregister_chrdev(unsignedintmajor,constchar*name,conststructfile_operations*fops){structchar_device_struct*cd;structcdev*cdev;char*s;interr=-ENOMEM;cd=__register_chrdev_region(major,0,256,name);if(IS_ERR(cd))returnPTR_ERR(cd);cdev=cdev_alloc();if(!cdev)gotoout2;cdev-owner=fops-owner;cdev-ops=fops;//注意,在后面的chrdev_open会从cdev再得到fops...}file:fs/char_dev.cintcdev_add(structcdev*p,dev_tdev,unsignedcount){p-dev=dev;p-count=count;returnkobj_map(cdev_map,dev,count,NULL,exact_match,exact_lock,p);}file:fs/char_dev.cstaticstructkobject*exact_match(dev_tdev,int*part,void*data){structcdev*p=data;return&p-kobj;}file:drivers/base/map.cintkobj_map(structkobj_map*domain,dev_tdev,unsignedlongrange,structmodule*module,kobj_probe_t*probe,int(*lock)(dev_t,void*),void*data){unsignedn=MAJOR(dev+range-1)-MAJOR(dev)+1;unsignedindex=MAJOR(dev);unsignedi;structprobe*p;if(n255)n=255;p=kmalloc(sizeof(structprobe)*n,GFP_KERNEL);if(p==NULL)return-ENOMEM;for(i=0;in;i++,p++){p-owner=module;p-get=probe;//此处其实就是exact_matchp-lock=lock;p-dev=dev;p-range=range;p-data=data;}mutex_lock(domain-lock);for(i=0,p-=n;in;i++,p++,index++){structprobe**s=&domain-probes[index%255];while(*s&&(*s)-rangerange)s=&(*s)-next;p-next=*s;*s=p;}mutex_unlock(domain-lock);return0;}【参考UnderstandingTheLinuxKernel13.5.CharacterDeviceDrivers】Thedevicedrivermodeldefinesakobjectmappingdomainforthecharacterdevices,whichisrepresentedbyadescriptoroftypekobj_mapandisreferencedbythecdev_mapglobalvariable.Thekobj_mapdescriptorincludesahashtableof255entriesindexedbythemajornumberoftheintervals.Thehashtablestoresobjectsoftypeprobe,oneforeachregisteredrangeofmajorandminornumbers,whosefieldsarelistedinTable13-9.Whenthekobj_map()functionisinvoked,thespecifiedintervalofdevicenumbersisaddedtothehashtable.Thedatafieldofthecorrespondingprobeobjectpointstothecdevdescriptorofthedevicedriver.Thevalueofthisfieldispassedtothegetandlockmethodswhentheyareexecuted.Inthiscase,thegetmethodisimplementedbyashortfunctionthatreturnstheaddressofthekobjectembeddedinthecdevdescriptor;thelockmethod,instead,essentiallyincreasesthereferencecounterintheembeddedkobject.Thekobj_lookup()functionreceivesasinputparametersakobjectmappingdomainandadevicenumber;itsearchesthehashtableandreturnstheaddressofthekobjectoftheowneroftheintervalincludingthenumber,ifitwasfound.Whenappliedtothemappingdomainofthecharacterdevices,thefunctionreturnstheaddressofthekobjectembeddedinthecdevdescriptorofthedevicedriverthatownstheintervalofdevicenumbers.二)从系统调用往内核走,看当初驱动里注册的file_operations里的open函数怎么被调用的sys_open-do_sys_open-do_filp_open-nameidata_to_filp-__dentry_open问题是1)__dentry_open如何找到chrdev_open?2)最终又是如何调用file_operations里的在驱动里面注册的open函数的呢?staticstructfile*__dentry_open(structdentry*dentry,structvfsmount*mnt,intflags,structfile*f,int(*open)(structinode*,structfile*)){structinode*inode;interror;f-f_flags=flags;f-f_mode=((flags+1)&O_ACCMODE)|FMODE_LSEEK|FMODE_PREAD|FMODE_PWRITE;inode=dentry-d_inode;if(f-f_mode&FMODE_WRITE){error=__get_file_write_access(inode,mnt);if(error)gotocleanup_file;if(!special_file(inode-i_mode))file_take_write(f);}f-f_mapping=inode-i_mapping;f-f_path.dentry=dentry;f-f_path.mnt=mnt;f-f_pos=0;f-f_op=fops_get(inode-i_fop);//此处获得def_chr_fopsfile_move(f,&inode-i_sb-s_files);error=security_dentry_open(f);if(error)gotocleanup_all;if(!open&&f-f_op)open=f-f_op-open;//此处调用def_chr_fops里的open函数,即chrdev_open...}file:fs/char_dev.cchrdev_open(){structcdev*p;structcdev*new=NULL;intret=0;spin_lock(&cdev_lock);p=inode-i_cdev;if(!p){structkobject*kobj;intidx;spin_unlock(&cdev_lock);kobj=kobj_lookup(cdev_map,inode-i_rdev,&idx);//找到cdev对应的kobj对象,跟kobj_map遥相对应的,反操作if(!kobj)return-ENXIO;new=container_of(kobj,structcdev,kobj);//找到cdevspin_lock(&cdev_lock);p=inode-i_cdev;if(!p){inode-i_cdev=p=new;inode-i_cindex=idx;list_add(&inode-i_devices,&p-list);new=NULL;}elseif(!cdev_get(p))ret=-ENXIO;}elseif(!cdev_get(p))ret=-ENXIO;spin_unlock(&cdev_lock);cdev_put(new);if(ret)returnret;filp-f_op=fops_get(p-ops);//这里又找回了当初驱动注册时的file_operations指针if(!filp-f_op){cdev_put(p);return-ENXIO;}if(filp-f_op-open){lock_kernel();ret=filp-f_op-open(inode,filp);//此处算真正的调用了file_operations里的open函数unlock_kernel();}...}file:drivers/base/map.cstructkobject*kobj_lookup(structkobj_map*domain,dev_tdev,int*index){structkobject*kobj;structprobe*p;unsignedlongbest=~0UL;retry:mutex_lock(domain-lock);for(p=domain-probes[MAJOR(dev)%255];p;p=p-next){structkobject*(*probe)(dev_t,int*,void*);structmodule*owner;void*data;if(p-devdev||p-dev+p-range-1dev)continue;if(p-range-1=best)break;if(!try_module_get(p-owner))continue;owner=p-owner;data=p-data;probe=p-get;//这里其实就是exact_match函数了best=p-range-1;*index=dev-p-dev;if(p-lock&&p-lock(dev,data)0){module_put(owner);continue;}mutex_unlock(domain-lock);kobj=probe(dev,index,data);//这里调用了exact_match函数/*Currently-ownerprotects_only_-probe()itself.*/module_put(owner);if(kobj)returnkobj;gotor