视窗
loading...
您现在的位置:首页 > IT认证 > Linux认证 >

Linux自动创建设备节点


在驱动用加入对udev的支持主要做的就是:在驱动初始化的代码里调用class_create(…)为该设备创建一个class,再为每个设备调用device_create(…)( 在2.6较早的内核中用class_device_create)创建对应的设备。
   
    内核中定义的struct class结构体,顾名思义,一个struct class结构体类型变量对应一个类,内核同时提供了class_create(…)函数,可以用它来创建一个类,这个类存放于sysfs下面,一旦创建好了这个类,再调用 device_create(…)函数来在/dev目录下创建相应的设备节点。这样,加载模块的时候,用户空间中的udev会自动响应 device_create(…)函数,去/sysfs下寻找对应的类从而创建设备节点。
   
    struct class定义在头文件include/linux/device.h中class_create(…)在/drivers/base/class.c中实现device_create(…)函数在/drivers/base/core.c中实现class_destroy(…),device_destroy(…)也在/drivers/base/core.c中实现调用过程类似如下:
   
    static struct class *spidev_class;
   
    /*-------------------------------------------------------------------------*/
   
    static int spidev_probe(struct spi_device *spi)
   
    {
   
    …
   
    dev = device_create(spidev_class, &spi->dev, spidev->devt,
   
    spidev, "spidev%d.%d",
   
    spi->master->bus_num, spi->chip_select);
   
    …
   
    }
   
    static int spidev_remove(struct spi_device *spi)
   
    {
   
    ……
   
    device_destroy(spidev_class, spidev->devt);
   
    ……
   
    return 0;
   
    }
   
    static struct spi_driver spidev_spi = {
   
    .driver = {
   
    .name =        "spidev",
   
    .owner =    THIS_MODULE,
   
    },
   
    .probe =    spidev_probe,
   
    .remove =    __devexit_p(spidev_remove),
   
    };
   
    /*-------------------------------------------------------------------------*/
   
    static int __init spidev_init(void)
   
    {
   
    …
   
    spidev_class = class_create(THIS_MODULE, "spidev");
   
    if (IS_ERR(spidev_class)) {
   
    unregister_chrdev(SPIDEV_MAJOR, spidev_spi.driver.name);
   
    return PTR_ERR(spidev_class);
   
    }
   
    …
   
    }
   
    module_init(spidev_init);
   
    static void __exit spidev_exit(void)
   
    {
   
    ……
   
    class_destroy(spidev_class);
   
    ……
   
    }
   
    module_exit(spidev_exit);
   
    MODULE_DESCRIPTION("User mode SPI device interface");
   
    MODULE_LICENSE("GPL");
   
    下面以一个简单字符设备驱动来展示如何使用这几个函数
   
    #include <linux/module.h>
   
    #include <linux/kernel.h>
   
    #include <linux/init.h>
   
    #include <linux/fs.h>
   
    #include <linux/cdev.h>
   
    #include <linux/device.h>
   
    int HELLO_MAJOR = 0;
   
    int HELLO_MINOR = 0;
   
    int NUMBER_OF_DEVICES = 2;
   
    struct class *my_class;
   
    struct cdev cdev; dev_t devno;
   
    struct file_operations hello_fops = {
   
    .owner = THIS_MODULE
   
    };
   
    static int __init hello_init (void)
   
    {
   
    int result;
   
    devno = MKDEV(HELLO_MAJOR, HELLO_MINOR);
   
    if (HELLO_MAJOR)
   
    result = register_chrdev_region(devno, 2, "memdev");
   
    else
   
    {
   
    result = alloc_chrdev_region(&devno, 0, 2, "memdev");
   
    HELLO_MAJOR = MAJOR(devno);
   
    }
   
    printk("MAJOR IS %d\n",HELLO_MAJOR);
   
    my_class = class_create(THIS_MODULE,"hello_char_class");  //类名为hello_char_class
   
    if(IS_ERR(my_class))
   
    {
   
    printk("Err: failed in creating class.\n");
   
    return -1;
   
    }
   
    device_create(my_class,NULL,devno,NULL,"memdev");      //设备名为memdev
   
    if (result<0)
   
    {
   
    printk (KERN_WARNING "hello: can't get major number %d\n", HELLO_MAJOR);
   
    return result;
   
    }
   
    cdev_init(&cdev, &hello_fops);
   
    cdev.owner = THIS_MODULE;
   
    cdev_add(&cdev, devno, NUMBER_OF_DEVICES);
   
    printk (KERN_INFO "Character driver Registered\n");
   
    return 0;
   
    }
   
    static void __exit hello_exit (void)
   
    {
   
    cdev_del (&cdev);
   
    device_destroy(my_class, devno);         //delete device node under /dev//必须先删除设备,再删除class类
   
    class_destroy(my_class);                 //delete class created by us
   
    unregister_chrdev_region (devno,NUMBER_OF_DEVICES);
   
    printk (KERN_INFO "char driver cleaned up\n");
   
    }
   
    module_init (hello_init);
   
    module_exit (hello_exit);
   
    MODULE_LICENSE ("GPL");
   
    这样,模块加载后,就能在/dev目录下找到memdev这个设备节点了。
   
    例2:内核中的drivers/i2c/i2c-dev.c
   
    在i2cdev_attach_adapter中调用device_create(i2c_dev_class, &adap->dev,
   
    MKDEV(I2C_MAJOR, adap->nr), NULL,
   
    "i2c-%d", adap->nr);
   
    这样在dev目录就产生i2c-0  或i2c-1节点
   
    接下来就是udev应用,udev是应用层的东西,udev需要内核sysfs和tmpfa的支持,sysfs为udev提供设备入口和uevent通道,tmpfs为udev设备文件提供存放空间
   
    udev的源码可以在去相关网站下载,然后就是对其在运行环境下的移植,指定交叉编译环境,修改Makefile下的CROSS_COMPILE,如为mipsel-linux-,DESTDIR=xxx,或直接make CROSS_COMPILE=mipsel-linux-,DESTDIR=xxx 并install把主要生成的udevd、udevstart拷贝rootfs下的/sbin/目录内,udev的配置文件udev.conf和rules.d下的rules文件拷贝到rootfs下的/etc/目录内,并在rootfs/etc/init.d/rcS中添加以下几行:
   
    echo "Starting udevd…"
   
    /sbin/udevd --daemon
   
    /sbin/udevstart
   
    (原rcS内容如下:
   
    # mount filesystems
   
    /bin/mount -t proc /proc /proc
   
    /bin/mount -t sysfs sysfs /sys
   
    /bin/mount -t tmpfs tmpfs /dev
   
    # create necessary devices
   
    /bin/mknod /dev/null c 1 3
   
    /bin/mkdir /dev/pts
   
    /bin/mount -t devpts devpts /dev/pts
   
    /bin/mknod /dev/audio c 14 4
   
    /bin/mknod /dev/ts c 10 16
   
    )
   
    这样当系统启动后,udevd和udevstart就会解析配置文件,并自动在/dev下创建设备节点文件
闂傚倸鍊风欢姘缚瑜嶈灋婵炲棙鎸哥粈澶愭煛閸ャ儱鐏╅柛灞诲姂閺屾洟宕煎┑鍥ь槱闁诲孩鑹鹃…鐑藉蓟閵娿儮鏀介柛鈩兠悵鏃傜磽娴g懓鏁剧紓宥勭窔瀵鏁撻悩鑼槹濡炪倖鍔х€靛矂鍩€椤掍緡娈滈柡宀€鍠栭幗搴ㄥ磼濮橆剛銈梻浣筋嚃閸燁偊宕惰閸炲爼姊虹紒妯荤叆闁硅姤绮庣划鏃堫敆閸曨剛鍘介梺缁樏鍫曞箹閹扮増鐓熼幒鎶藉礉鐏炶棄绁梻浣侯攰閹活亞绮婚幋锝囩闂傚倷娴囧▔鏇㈠闯閿曞倸绠柨鐕傛嫹
闂傚倸鍊风粈渚€骞栭锔藉亱婵犲﹤鐗嗙粈鍫熺箾閹存瑥鐏柛瀣枑閵囧嫰寮介顫勃闂佺粯甯$粻鏍蓟閺囩喓绠鹃柛顭戝枛婵酣姊虹拠鍙夊攭妞ゆ泦鍡楃倒闂備焦鎮堕崕鑽ゅ緤閼恒儲娅犻柟缁樺础瑜版帗鍋傞幖娣灩濞堟鎮楀▓鍨灈闁绘牕鍚嬫穱濠囨倻閼恒儲娅嗛梺鍛婃寙閸愵亜甯楀┑鐘垫暩閸嬫盯鎮洪妸褍鍨濈€光偓閳ь剟鎳為柆宥嗗殐闁冲搫瀚皬濠电偛顕崢褔鎮洪妸鈺佸惞闁稿瞼鍋為悡娑㈡煕閹扳晛濡奸柍褜鍓濆畷鐢靛垝閺冨洢浜归柟鐑樻尵閸欏棗鈹戦悙鏉戠伇婵炲懏娲滈埀顒佺啲閹凤拷闂傚倷娴囬褍霉閻戣棄鏋侀柟闂撮檷閳ь兛鐒︾换婵嬪磻椤栨氨绉虹€规洖宕灒閻犲洤妯婂ḿ顖炴⒒娴i涓茬紒韫矙瀵敻顢楅崟顒€浠奸梺鍛婎殘閸婃垶鎯旈妸銉у€為梺鎸庣箓閹冲酣鍩涙径瀣閻庣數枪鐢爼鏌熼搹顐€块柣娑卞枤閳ь剨缍嗛崰鏍不閿濆棛绡€濠电姴鍊搁顐︽煙閺嬵偄濮傛慨濠冩そ瀹曘劍绻濋崘锝嗗缂傚倷绀侀鍡欐暜閿熺姴绠氶柛銉e妼椤曢亶鏌℃径瀣仴闁哥偑鍔戝娲箹閻愭彃濮岄梺鍛婃煥缁夊綊鏁愰悙鍝勫唨妞ゎ兙鍎遍柊锝呯暦閸洘鏅查柛娑卞幐閹枫倕鈹戦悙宸殶闁告鍥х疇婵せ鍋撴鐐叉瀹曟﹢顢欓懖鈺婃Ч婵$偑鍊栭崝鎴﹀垂濞差亝鍎婇柡鍐e亾缂佺粯绻堟慨鈧柨婵嗘閵嗘劙鏌f惔銏e闁硅姤绮屽嵄闁规壆澧楅弲鎼佹煥閻曞倹瀚�闂傚倸鍊烽懗鍫曞箠閹剧粯鍋ら柕濞炬櫅閸ㄥ倿鏌涢幇顓犮偞闁割偒浜弻鐔衡偓鐢登瑰皬闂佺粯甯掗敃銈夊煘閹达附鍋愰柛娆忣槹閹瑥鈹戦悙鍙夊櫡闁搞劌缍婂﹢渚€姊洪幐搴g畵婵☆偅鐩幆灞炬償閵婏妇鍘撻悷婊勭矒瀹曟粌鈻庨幘宕囩枃闂佸綊鍋婇崗姗€寮搁弮鍫熺厵閺夊牓绠栧顕€鏌涚€n亶鍎旈柡灞剧洴椤㈡洟濡堕崨顔锯偓鍓х磽閸屾氨袦闁稿鎹囧缁樻媴閻熸壆浜伴梺缁樺釜缁犳挻淇婇悽鍛婂€烽柣銏㈡暩椤︻垶姊洪崫鍕殭闁绘妫涢惀顏囶樄闁哄本鐩獮鍥敍濞戞哎鈧﹦绱撴担鎻掍壕闂佽法鍣﹂幏锟�闂傚倷娴囬褏鑺遍懖鈺佺筏濠电姵鐔紞鏍ь熆閼搁潧濮囬柛銊ュ€圭换婵囩節閸屾凹浼€濡炪倐鏅犻弨閬嶅Φ閸曨垰绠抽柟瀛樼箖濞堣尙绱撴担椋庤窗闁革綇绲介锝夊醇閺囩喎鈧兘鏌涢…鎴濅簼闁绘繍浜滈埞鎴︽倷閼碱剙顤€闂佹悶鍔屾晶搴e垝濮樿埖鐒肩€广儱鎳愰崝鎾⒑閸涘﹤澹冮柛娑卞灱濡差剚绻濋悽闈浶ユい锝勭矙閸┾偓妞ゆ巻鍋撻柛鐔锋健閸┾偓妞ゆ帒鍊归崵鈧梺鎸庢磸閸ㄦ椽骞忛崨鏉戠闁圭粯甯楅鍧楁⒒娴e懙褰掑嫉椤掑倹宕茬€广儱顦懜褰掓煙缂併垹鏋熼柣鎾寸懇閹鈽夊▎瀣窗婵犫拃灞藉缂佺粯绻堥崺鈧い鎺嶇劍婵挳鏌涢敂璇插箻闁硅櫕绻堝娲礈閼碱剙甯ラ梺绋款儏閹虫劗妲愰悙鍝勭劦妞ゆ帒瀚埛鎴︽煟閻旂ǹ顥嬮柟鐣屽█閺岋絽螖閸愩劋鎴烽梺鐟扮畭閸ㄥ綊锝炲┑瀣垫晞闁兼亽鍎虫禍娆撴⒒娴e憡鎯堟繛璇х畵閹矂顢欓悙顒€搴婇梺绯曞墲缁嬫帡鎮″▎鎰╀簻闁圭偓顨呴崯鐗堢閺夋埈娓婚柕鍫濇婢跺嫰鏌涢幘璺烘瀻闁伙絿鍏橀弫鎰板幢濞嗘垹妲囬梻浣告啞閸斿繘寮查埡浣勶綁顢涢悙绮规嫼闂佸ジ鈧稑宓嗛柛婵堝劋閹便劍绻濋崒銈囧悑闂佸搫鑻悧鎾荤嵁濮椻偓椤㈡瑩鎳栭埡濠傛倛闂傚倷鑳堕幊鎾绘偤閵娧冨灊鐎广儱娲ら崹婵嬫煥閺囩偛鈧綊鎮¢妷锔剧闁瑰鍊栭幋婵撹€块柣妤€鐗忕弧鈧梺閫炲苯澧存鐐茬Ч椤㈡瑩骞嗚鐟欙附绻濋悽闈涗粶婵☆偅顨呴湁濡炲娴烽悳缁樹繆閵堝懎鏆熺痪鎯с偢閺岋繝宕掑☉鍗炲妼闂佺ǹ楠哥换鎺楀焵椤掑喚娼愰柟鍝デ硅灋婵犻潧妫涢弳锔芥叏濡灝鐓愰柛瀣姉缁辨挻鎷呯拹顖滅窗閻熸粎澧楅崹鍨潖濞差亜绠伴幖绮光偓铏亞闂備胶鎳撻崵鏍箯閿燂拷闂傚倷娴囬褍霉閻戣棄鏋侀柟闂寸缁犵娀鏌熼幑鎰厫闁哄棙绮嶉妵鍕箛閸撲胶鏆犵紓浣插亾闁糕剝岣跨粻楣冩煙鐎甸晲绱虫い蹇撶墕閺嬩線鏌涢锝嗙闁稿﹦鏁搁惀顏堫敇閻愭潙顎涘┑鐐插悑閸旀瑩寮诲☉銏犖╅柨鏂垮⒔閻撲胶绱撴担绋库偓鍦暜閿熺姰鈧礁螖娴g懓顎撶紓浣割儏閺呮繈顢曢敂瑙f嫼闁荤喐鐟ョ€氼厾娆㈤懠顒傜<缂備焦锚閻忓鈧鍣崑濠囥€佸▎鎾村仼鐎光偓婵犲啰銈┑鐘愁問閸犳濡靛☉銏犵;闁瑰墽绮悡鍐喐濠婂牆绀堟繛鍡樻尭绾惧綊鏌涘┑鍕姢缂佲偓婵犲洦鍊甸柨婵嗛閺嬬喖鏌涙惔锛勑ч柡灞剧洴瀵挳濡搁妷銉х憿闁荤喐绮庢晶妤冩暜濡ゅ懏鍋傞柍褜鍓欓—鍐Χ閸℃鐟ㄩ梺鎸庢穿婵″洨鍒掗崼銉︽櫢闁跨噦鎷�闂傚倸鍊峰ù鍥ㄧ珶閸喆浠堢紒瀣儥濞兼牕鈹戦悩宕囶暡闁绘帡绠栭弻鐔虹磼閵忕姵鐏堝┑鈽嗗亝閿曘垽寮婚敐澶嬪亜缂佸顑欏Λ鍡欑磼缂併垹骞愰柛瀣崌濮婄粯鎷呴悷閭﹀殝缂備礁顑嗙敮鎺楁偩濠靛绠瑰ù锝呮憸閿涙盯姊洪崫鍕犻柛鏂块叄閵嗗懘鎮滈懞銉у弳闂佺粯娲栭崐鍦偓姘炬嫹:webmaster@jscj.com闂傚倸鍊风欢姘缚瑜嶈灋鐎光偓閸曨偆锛涢梺鐟板⒔缁垶鎮¢悢鎼炰簻妞ゆ劦鍋勯獮妯肩磼娴e搫鍘撮柡宀嬬秮閺佸倻鎹勯妸褏鍘梻浣芥〃缁€浣虹矓瑜版帒鏋侀柟鍓х帛閺呮悂鏌ㄩ悤鍌涘4008816886

相关文章

无相关信息
更新时间2022-03-13 11:11:02【至顶部↑】
联系我们 | 邮件: webmaster@jscj.com | 客服热线电话:4008816886(QQ同号) |  濠电姷鏁搁崕鎴犵礊閳ь剚銇勯弴鍡楀閸欏繘鏌i幇顕呮毌闁稿鎹囬悰顕€宕归鍙ョ棯婵犵數濮崑鎾绘煕閵夋垵鑻▓顐㈩渻閵堝棙顥嗘い鏂匡功閹广垽鏁撻敓锟�

付款方式留言簿投诉中心网站纠错二维码手机版

客服电话: