¡¡¡¡Ëæ×ÅLinux2.6µÄ·¢²¼£¬ÓÉÓÚ2.6ÄÚºË×öÁ˽̵ĸĶ¯£¬¸÷¸öÉ豸µÄÇý¶¯³ÌÐòÔÚ²»Í¬³Ì¶ÈÉÏÒª½øÐиÄд¡£ÎªÁË·½±ã¸÷λLinux°®ºÃÕßÎÒ°Ñ×Ô¼ºÕûÀíµÄÕâ·ÖÎĵµshare³öÀ´¡£¸ÃÎĵ±ÁоÙÁË2.6ÄÚºËͬÒÔÇ°°æ±¾µÄ¾ø´ó¶àÊý±ä»¯£¬¿ÉϧµÄÊÇÓÉÓÚʱ¼äºÍ¾«Á¦ÓÐÏÞûÓÐÏêϸÁгö¸÷¸öº¯ÊýµÄÓ÷¨¡£
¡¡¡¡ÌرðÉùÃ÷£º¸ÃÎĵµÖеÄÄÚÈÝÀ´×Ôhttp://lwn.net£¬¸ÃÍøÒ²ÉÏÒ²Óи÷¸öº¯ÊýµÄ½ÏΪÏêϸµÄ˵Ã÷¿É¹©¸÷λ²Î¿¼¡£
¡¡¡¡1¡¢Ê¹ÓÃеÄÈë¿Ú
¡¡¡¡±ØÐë°üº¬ £¼linux/init.h£¾
¡¡¡¡module_init(your_init_func);
¡¡¡¡module_exit(your_exit_func);
¡¡¡¡ÀÏ°æ±¾£ºint init_module(void);
¡¡¡¡void cleanup_module(voi);
¡¡¡¡2.4ÖÐÁ½ÖÖ¶¼¿ÉÒÔÓ㬶ÔÈçºóÃæµÄÈë¿Úº¯Êý²»±ØÒªÏÔʾ°üº¬ÈκÎÍ·Îļþ¡£
¡¡¡¡2¡¢GPL
¡¡¡¡MODULE_LICENSE("Dual BSD/GPL");
¡¡¡¡ÀÏ°æ±¾£ºMODULE_LICENSE("GPL");
¡¡¡¡3¡¢Ä£¿é²ÎÊý
¡¡¡¡±ØÐëÏÔʽ°üº¬£¼linux/moduleparam.h£¾
¡¡¡¡module_param(name, type, perm);
¡¡¡¡module_param_named(name, value, type, perm);
¡¡¡¡²ÎÊý¶¨Òå
¡¡¡¡module_param_string(name, string, len, perm);
¡¡¡¡module_param_array(name, type, num, perm);
¡¡¡¡ÀÏ°æ±¾£ºMODULE_PARM(variable,type);
¡¡¡¡MODULE_PARM_DESC(variable,type);
¡¡¡¡4¡¢Ä£¿é±ðÃû
¡¡¡¡MODULE_ALIAS("alias-name");
¡¡¡¡ÕâÊÇÐÂÔöµÄ£¬ÔÚÀÏ°æ±¾ÖÐÐèÔÚ/etc/modules.confÅäÖã¬ÏÖÔÚÔÚ´úÂëÖоͿÉÒÔʵÏÖ¡£
¡¡¡¡5¡¢Ä£¿é¼ÆÊý
¡¡¡¡int try_module_get(&module);
¡¡¡¡module_put();
¡¡¡¡ÀÏ°æ±¾£ºMOD_INC_USE_COUNT ºÍ MOD_DEC_USE_COUNT
¡¡¡¡6¡¢·ûºÅµ¼³ö
¡¡¡¡Ö»ÓÐÏÔʾµÄµ¼³ö·ûºÅ²ÅÄܱ»ÆäËûÄ£¿éʹÓã¬Ä¬Èϲ»µ¼³öËùÓеķûºÅ£¬²»±ØʹÓÃEXPORT_NO_SYMBOLS
¡¡¡¡ÀÏ°å±¾£ºÄ¬Èϵ¼³öËùÓеķûºÅ£¬³ý·ÇʹÓÃEXPORT_NO_SYMBOLS
¡¡¡¡7¡¢Äں˰汾¼ì²é
¡¡¡¡ÐèÒªÔÚ¶à¸öÎļþÖаüº¬£¼linux/module.h£¾Ê±£¬²»±Ø¶¨Òå__NO_VERSION__
¡¡¡¡ÀÏ°æ±¾£ºÔÚ¶à¸öÎļþÖаüº¬£¼linux/module.h£¾Ê±£¬³ýÔÚÖ÷ÎļþÍâµÄÆäËûÎļþÖбØÐ붨Òå__NO_VERSION__£¬·ÀÖ¹°æ±¾Öظ´¶¨Òå¡£
¡¡¡¡8¡¢É豸ºÅ
¡¡¡¡kdev_t±»·Ï³ý²»¿ÉÓã¬ÐµÄdev_tÍØÕ¹µ½ÁË32룬12λÖ÷É豸ºÅ£¬20λ´ÎÉ豸ºÅ¡£
¡¡¡¡unsigned int iminor(strUCt inode *inode);
¡¡¡¡unsigned int imajor(struct inode *inode);
¡¡¡¡ÀÏ°æ±¾£º8λÖ÷É豸ºÅ£¬8λ´ÎÉ豸ºÅ
¡¡¡¡int MAJOR(kdev_t dev);
¡¡¡¡int MINOR(kdev_t dev);
¡¡¡¡9¡¢ÄÚ´æ·ÖÅäÍ·Îļþ±ä¸ü
¡¡¡¡ËùÓеÄÄÚ´æ·ÖÅ亯Êý°üº¬ÔÚÍ·Îļþ£¼linux/slab.h£¾£¬¶øÔÀ´µÄ£¼linux/malloc.h£¾²»´æÔÚ
¡¡¡¡ÀÏ°æ±¾£ºÄÚ´æ·ÖÅ亯Êý°üº¬ÔÚÍ·Îļþ£¼linux/malloc.h£¾
¡¡¡¡10¡¢½á¹¹ÌåµÄ³õÊÔ»¯
¡¡¡¡gcc¿ªÊ¼²ÉÓÃANSI CµÄstruct½á¹¹ÌåµÄ³õʼ»¯ÐÎʽ£º
¡¡¡¡static struct some_structure = {
¡¡¡¡.field1 = value,
¡¡¡¡.field2 = value,
¡¡¡¡..
¡¡¡¡};
¡¡¡¡ÀÏ°æ±¾£º·Ç±ê×¼µÄ³õÊÔ»¯ÐÎʽ
¡¡¡¡static struct some_structure = {
¡¡¡¡field1: value,
¡¡¡¡field2: value,
¡¡¡¡..
¡¡¡¡};
¡¡¡¡11¡¢Óû§Ä£Ê½°ïÖúÆ÷
¡¡¡¡int call_usermodehelper(char *path, char **argv, char **envp,int wait);
¡¡¡¡ÐÂÔöwait²ÎÊý
¡¡¡¡12¡¢request_module()
¡¡¡¡request_module("foo-device-%d", number);
¡¡¡¡ÀÏ°æ±¾£º
¡¡¡¡char module_name[32];
¡¡¡¡printf(module_name, "foo-device-%d", number);
¡¡¡¡request_module(module_name);
[1] [2] [3] ÏÂÒ»Ò³
¡¡¡¡13¡¢dev_tÒý·¢µÄ×Ö·ûÉ豸µÄ±ä»¯
¡¡¡¡1¡¢È¡Ö÷´ÎÉ豸ºÅΪ
¡¡¡¡unsigned iminor(struct inode *inode);
¡¡¡¡unsigned imajor(struct inode *inode);
¡¡¡¡2¡¢ÀϵÄregister_chrdev()Ó÷¨Ã»±ä£¬±£³ÖÏòºó¼æÈÝ£¬µ«²»ÄÜ·ÃÎÊÉ豸ºÅ´óÓÚ256µÄÉ豸¡£
¡¡¡¡3¡¢ÐµĽӿÚΪ
¡¡¡¡a)×¢²á×Ö·ûÉ豸·¶Î§
¡¡¡¡int register_chrdev_region(dev_t from, unsigned count, char *name);
¡¡¡¡b)¶¯Ì¬ÉêÇëÖ÷É豸ºÅ
¡¡¡¡int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, char
¡¡¡¡*name);
¡¡¡¡¿´ÁËÕâÁ½¸öº¯ÊýÓôÃÆ°É^_^£¡ÔõôºÍfile_operations½á¹¹ÁªÏµÆðÀ´°¡£¿±ð¼±£¡
¡¡¡¡c)°üº¬ £¼linux/cdev.h£¾£¬ÀûÓÃstruct cdevºÍfile_operationsÁ¬½Ó
¡¡¡¡struct cdev *cdev_alloc(void);
¡¡¡¡void cdev_init(struct cdev *cdev, struct file_operations *fops);
¡¡¡¡int cdev_add(struct cdev *cdev, dev_t dev, unsigned count);
¡¡¡¡£¨·Ö±ðΪ£¬ÉêÇëcdev½á¹¹£¬ºÍfopsÁ¬½Ó£¬½«É豸¼ÓÈ뵽ϵͳÖУ¡ºÃ¸´ÔÓ°¡£¡£©
¡¡¡¡d)void cdev_del(struct cdev *cdev);
¡¡¡¡Ö»ÓÐÔÚcdev_addÖ´Ðгɹ¦²Å¿ÉÔËÐС£
¡¡¡¡e)¸¨Öúº¯Êý
¡¡¡¡kobject_put(&cdev-£¾kobj);
¡¡¡¡struct kobject *cdev_get(struct cdev *cdev);
¡¡¡¡void cdev_put(struct cdev *cdev);
¡¡¡¡ÕâÒ»²¿·Ö±ä»¯ºÍÐÂÔöµÄ/sys/devÓÐÒ»¶¨µÄ¹ØÁª¡£
¡¡¡¡14¡¢ÐÂÔö¶Ô/procµÄ·ÃÎʲÙ×÷
¡¡¡¡£¼linux/seq_file.h£¾
¡¡¡¡ÒÔÇ°µÄ/procÖÐÖ»Äܵõ½string, seq_file²Ù×÷Äܵõ½ÈçlongµÈ¶àÖÖÊý¾Ý¡£
¡¡¡¡Ïà¹Øº¯Êý£º
¡¡¡¡static struct seq_operations ±ØÐëʵÏÖÕâ¸öÀàËÆfile_operationsµÃÊý¾ÝÖеø÷¸ö³É
¡¡¡¡Ô±º¯Êý¡£
¡¡¡¡seq_printf()£»
¡¡¡¡int seq_putc(struct seq_file *m, char c);
¡¡¡¡int seq_puts(struct seq_file *m, const char *s);
¡¡¡¡int seq_escape(struct seq_file *m, const char *s, const char *esc);
¡¡¡¡int seq_path(struct seq_file *m, struct vfsmount *mnt,
¡¡¡¡struct dentry *dentry, char *esc);
¡¡¡¡seq_open(file, &ct_seq_ops);
¡¡¡¡µÈµÈ
¡¡¡¡15¡¢µ×²ãÄÚ´æ·ÖÅä
¡¡¡¡1¡¢£¼linux/malloc.h£¾Í·Îļþ¸ÄΪ£¼linux/slab.h£¾
¡¡¡¡2¡¢·ÖÅä±êÖ¾GFP_BUFFER±»È¡Ïû£¬È¡¶ø´úÖ®µÄÊÇGFP_NOIO ºÍ GFP_NOFS
¡¡¡¡3¡¢ÐÂÔö__GFP_REPEAT£¬__GFP_NOFAIL£¬__GFP_NORETRY·ÖÅä±êÖ¾
¡¡¡¡4¡¢Ò³Ãæ·ÖÅ亯Êýalloc_pages()£¬get_free_page()±»°üº¬ÔÚ£¼linux/gfp.h£¾ÖÐ
¡¡¡¡5¡¢¶ÔNUMAϵͳÐÂÔöÁ˼¸¸öº¯Êý£º
¡¡¡¡a) struct page *alloc_pages_node(int node_id,
¡¡¡¡unsigned int gfp_mask,
¡¡¡¡unsigned int order);
¡¡¡¡b) void free_hot_page(struct page *page);
¡¡¡¡c) void free_cold_page(struct page *page);
¡¡¡¡6¡¢ ÐÂÔöMemory pools
¡¡¡¡£¼linux/mempool.h£¾
¡¡¡¡mempool_t *mempool_create(int min_nr,
¡¡¡¡mempool_alloc_t *alloc_fn,
¡¡¡¡mempool_free_t *free_fn,
¡¡¡¡void *pool_data);
¡¡¡¡void *mempool_alloc(mempool_t *pool, int gfp_mask);
¡¡¡¡void mempool_free(void *element, mempool_t *pool);
¡¡¡¡int mempool_resize(mempool_t *pool, int new_min_nr, int gfp_mask);
¡¡¡¡16¡¢ per-CPU±äÁ¿
¡¡¡¡get_cpu_var();
¡¡¡¡put_cpu_var();
¡¡¡¡void *alloc_percpu(type);
¡¡¡¡void free_percpu(const void *);
¡¡¡¡per_cpu_ptr(void *ptr, int cpu)
¡¡¡¡get_cpu_ptr(ptr)
¡¡¡¡put_cpu_ptr(ptr)
¡¡¡¡Àϰ汾ʹÓÃ
¡¡¡¡DEFINE_PER_CPU(type, name);
ÉÏÒ»Ò³ [1] [2] [3] ÏÂÒ»Ò³
¡¡¡¡EXPORT_PER_CPU_SYMBOL(name);
¡¡¡¡EXPORT_PER_CPU_SYMBOL_GPL(name);
¡¡¡¡DECLARE_PER_CPU(type, name);
¡¡¡¡DEFINE_PER_CPU(int, mypcint);
¡¡¡¡2.6Äں˲ÉÓÃÁË¿É°þ¶áµÃµ÷¶È·½Ê½ÕâЩºê¶¼²»°²È«¡£
¡¡¡¡17¡¢ÄÚºËʱ¼ä±ä»¯
¡¡¡¡1¡¢ÏÖÔڵĸ÷¸öƽ̨µÄHZΪ
¡¡¡¡Alpha: 1024/1200; ARM: 100/128/200/1000; CRIS: 100; i386: 1000; IA-64:
¡¡¡¡1024; M68K: 100; M68K-nommu: 50-1000; MIPS: 100/128/1000; MIPS64: 100;
¡¡¡¡PA-RISC: 100/1000; PowerPC32: 100; PowerPC64: 1000; S/390: 100; SPARC32:
¡¡¡¡100; SPARC64: 100; SuperH: 100/1000; UML: 100; v850: 24-100; x86-64: 1000.
¡¡¡¡2¡¢ÓÉÓÚHZµÄ±ä»¯£¬ÔÀ´µÄjiffies¼ÆÊýÆ÷ºÜ¿ì¾ÍÒç³öÁË£¬ÒýÈëÁËеļÆÊýÆ÷jiffies_64
¡¡¡¡3¡¢#include £¼linux/jiffies.h£¾
¡¡¡¡u64 my_time = get_jiffies_64();
¡¡¡¡4¡¢ÐµÄʱ¼ä½á¹¹Ôö¼ÓÁËÄÉÃë³ÉÔ±±äÁ¿
¡¡¡¡struct timespec current_kernel_time(void);
¡¡¡¡5¡¢ËûµÄtimerº¯Êýû±ä£¬ÐÂÔö
¡¡¡¡void add_timer_on(struct timer_list *timer, int cpu);
¡¡¡¡6¡¢ÐÂÔöÄÉÃ뼶ÑÓʱº¯Êý
¡¡¡¡ndelay()£»
¡¡¡¡7¡¢POSIX clocks ²Î¿¼kernel/posix-timers.c
¡¡¡¡18¡¢¹¤×÷¶ÓÁУ¨workqueue£©
¡¡¡¡1¡¢ÈÎÎñ¶ÓÁУ¨task queue £©½Ó¿Úº¯Êý¶¼±»È¡Ïû£¬ÐÂÔöÁËworkqueue½Ó¿Úº¯Êý
¡¡¡¡struct workqueue_struct *create_workqueue(const char *name);
¡¡¡¡DECLARE_WORK(name, void (*function)(void *), void *data);
¡¡¡¡INIT_WORK(struct work_struct *work,
¡¡¡¡void (*function)(void *), void *data);
¡¡¡¡PREPARE_WORK(struct work_struct *work,
¡¡¡¡void (*function)(void *), void *data);
¡¡¡¡2¡¢ÉêÃ÷struct work_struct½á¹¹
¡¡¡¡int queue_work(struct workqueue_struct *queue,
¡¡¡¡struct work_struct *work);
¡¡¡¡int queue_delayed_work(struct workqueue_struct *queue,
¡¡¡¡struct work_struct *work,
¡¡¡¡unsigned long delay);
¡¡¡¡int cancel_delayed_work(struct work_struct *work);
¡¡¡¡void flush_workqueue(struct workqueue_struct *queue);
¡¡¡¡void destroy_workqueue(struct workqueue_struct *queue);
¡¡¡¡int schedule_work(struct work_struct *work);
¡¡¡¡int schedule_delayed_work(struct work_struct *work, unsigned long
¡¡¡¡delay);
£¨³ö´¦£ºhttp://www.sheup.com£©
¡¡¡¡struct work_struct *work);
¡¡¡¡int queue_delayed_work(struct workqueue_struct *queue,
¡¡¡¡struct work_struct *work,
¡¡¡¡unsigned long delay);
¡¡¡¡int cancel_delayed_work(struct work_struct *work);
¡¡¡¡void flush_workqueue(struct workqueue_struct *queue);
¡¡¡¡void destroy_workqueue(struct workqueue_struct *queue);
¡¡¡¡int schedule_work(struct work_struct *work);
¡¡¡¡int schedule_delayed_work(struct work_struct *work, unsigned long
¡¡¡¡delay);
£¨³ö´¦£ºhttp://www.sheup.com£©