内核模块代码中的特性

编程入门 行业动态 更新时间:2024-10-24 20:12:49

<a href=https://www.elefans.com/category/jswz/34/1769575.html style=内核模块代码中的特性"/>

内核模块代码中的特性

标记了__init和__exit的函数,都是作用于模块的;
__init:是载入模块时执行的操作
__exit:是卸载模块时的操作

printk是用来打印内核信息的函数,会将信息保存在系统日志,或是打印在控制台上;是否打印在控制台是取决于当前控制台日志级别,具体baidu
已下是printk的日志级别

#define KERN_EMERG"<0>"/*紧急事件消息,系统崩溃之前提示,表示系统不可用*/
#define KERN_ALERT"<1>"/*报告消息,表示必须立即采取措施*/
#define KERN_CRIT"<2>"/*临界条件,通常涉及严重的硬件或软件操作失败*/
#define KERN_ERR"<3>"/*错误条件,驱动程序常用KERN_ERR来报告硬件的错误*/
#define KERN_WARNING"<4>"/*警告条件,对可能出现问题的情况进行警告*/
#define KERN_NOTICE"<5>"/*正常但又重要的条件,用于提醒。常 用于与安全相关的消息*/
#define KERN_INFO"<6>"/*提示信息,如驱动程序启动时,打印硬件信息*/
#define KERN_DEBUG"<7>"/*调试级别的消息*/

module结构体:

linux/module.c

try_module_get()函数:

struct module {enum module_state state;/* Member of list of modules */struct list_head list;/* Unique handle for this module */char name[MODULE_NAME_LEN];/* Sysfs stuff. */struct module_kobject mkobj;struct module_attribute *modinfo_attrs;const char *version;const char *srcversion;struct kobject *holders_dir;/* Exported symbols */const struct kernel_symbol *syms;const s32 *crcs;unsigned int num_syms;/* Kernel parameters. */
#ifdef CONFIG_SYSFSstruct mutex param_lock;
#endifstruct kernel_param *kp;unsigned int num_kp;/* GPL-only exported symbols. */unsigned int num_gpl_syms;const struct kernel_symbol *gpl_syms;const s32 *gpl_crcs;#ifdef CONFIG_UNUSED_SYMBOLS/* unused exported symbols. */const struct kernel_symbol *unused_syms;const s32 *unused_crcs;unsigned int num_unused_syms;/* GPL-only, unused exported symbols. */unsigned int num_unused_gpl_syms;const struct kernel_symbol *unused_gpl_syms;const s32 *unused_gpl_crcs;
#endif#ifdef CONFIG_MODULE_SIG/* Signature was verified. */bool sig_ok;
#endifbool async_probe_requested;/* symbols that will be GPL-only in the near future. */const struct kernel_symbol *gpl_future_syms;const s32 *gpl_future_crcs;unsigned int num_gpl_future_syms;/* Exception table */unsigned int num_exentries;struct exception_table_entry *extable;/* Startup function. */int (*init)(void);/* Core layout: rbtree is accessed frequently, so keep together. */struct module_layout core_layout __module_layout_align;struct module_layout init_layout;/* Arch-specific module values */struct mod_arch_specific arch;unsigned long taints;   /* same bits as kernel:taint_flags */#ifdef CONFIG_GENERIC_BUG/* Support for BUG */unsigned num_bugs;struct list_head bug_list;struct bug_entry *bug_table;
#endif#ifdef CONFIG_KALLSYMS/* Protected by RCU and/or module_mutex: use rcu_dereference() */struct mod_kallsyms __rcu *kallsyms;struct mod_kallsyms core_kallsyms;/* Section attributes */struct module_sect_attrs *sect_attrs;/* Notes attributes */struct module_notes_attrs *notes_attrs;
#endif/* The command line arguments (may be mangled).  People likekeeping pointers to this stuff */char *args;#ifdef CONFIG_SMP/* Per-cpu data. */void __percpu *percpu;unsigned int percpu_size;
#endif#ifdef CONFIG_TRACEPOINTSunsigned int num_tracepoints;tracepoint_ptr_t *tracepoints_ptrs;
#endif
#ifdef CONFIG_TREE_SRCUunsigned int num_srcu_structs;struct srcu_struct **srcu_struct_ptrs;
#endif
#ifdef CONFIG_BPF_EVENTSunsigned int num_bpf_raw_events;struct bpf_raw_event_map *bpf_raw_events;
#endif
#ifdef CONFIG_JUMP_LABELstruct jump_entry *jump_entries;unsigned int num_jump_entries;
#endif
#ifdef CONFIG_TRACINGunsigned int num_trace_bprintk_fmt;const char **trace_bprintk_fmt_start;
#endif
#ifdef CONFIG_EVENT_TRACINGstruct trace_event_call **trace_events;unsigned int num_trace_events;struct trace_eval_map **trace_evals;unsigned int num_trace_evals;
#endif
#ifdef CONFIG_FTRACE_MCOUNT_RECORDunsigned int num_ftrace_callsites;unsigned long *ftrace_callsites;
#endif#ifdef CONFIG_LIVEPATCHbool klp; /* Is this a livepatch module? */bool klp_alive;/* Elf information */struct klp_modinfo *klp_info;
#endif#ifdef CONFIG_MODULE_UNLOAD/* What modules depend on me? */struct list_head source_list;/* What modules do I depend on? */struct list_head target_list;/* Destruction function. */void (*exit)(void);atomic_t refcnt;
#endif#ifdef CONFIG_CONSTRUCTORS/* Constructor functions. */ctor_fn_t *ctors;unsigned int num_ctors;
#endif#ifdef CONFIG_FUNCTION_ERROR_INJECTIONstruct error_injection_entry *ei_funcs;unsigned int num_ei_funcs;
#endif
} ____cacheline_aligned __randomize_layout;
#ifndef MODULE_ARCH_INIT

module结构体相当亢长,值得注意的几个:
里面的state是个枚举:

enum module_state {MODULE_STATE_LIVE,      /* Normal state. */MODULE_STATE_COMING,    /* Full formed, running module_init. */MODULE_STATE_GOING,     /* Going away. */MODULE_STATE_UNFORMED,  /* Still setting it up. */
};

refcnt为reference count,也就是module的被关联数;在module结构体中被定义为是个具有原子操作特性的atomic_t类型;

atomic_t refcnt;

try_module_get()函数用于判断module的状态(module_is_alive),以及atomic_inc_not_zero()函数判断module的refcnt是否大于0(等于0的话说明module目前是MODULE_STATE_GOING的状态,没办法get),大于0的话就将refcnt+1;

bool try_module_get(struct module *module)
{bool ret = true;if (module) {preempt_disable();/* Note: here, we can fail to get a reference */if (likely(module_is_live(module) &&atomic_inc_not_zero(&module->refcnt) != 0))trace_module_get(module, _RET_IP_);elseret = false;preempt_enable();}return ret;
}

若module在内核中,通过atomic_dec_if_positive()函数,在module的refcnt>0的时候将refcnt-1;
若对一个module做refcnt-1之后,ret<0了将会通过WARN_ON()来报warning;

void module_put(struct module *module)
{int ret;if (module) {preempt_disable();//下面是个原子操作,需要关闭抢占ret = atomic_dec_if_positive(&module->refcnt);WARN_ON(ret < 0);       /* Failed to put refcount */trace_module_put(module, _RET_IP_);preempt_enable();}
}

关于文件操作:

file_operations结构用于建立,设备编号和驱动程序之间的连接,结构定义在linux/fs.h中;
在Linux中,指向file_operation结构的指针称为fops,在file_operations这个结构中,每个字段都要指向驱动程序中实现特定操作的函数,对于不支持的操作可以指向NULL;
很多参数带有__user,__user这个前缀是用于表明指针是一个用户空间地址,检查防止对用户空间的错误使用;

struct file_operations {struct module *owner;loff_t (*llseek) (struct file *, loff_t, int);ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);int (*iopoll)(struct kiocb *kiocb, bool spin);int (*iterate) (struct file *, struct dir_context *);int (*iterate_shared) (struct file *, struct dir_context *);__poll_t (*poll) (struct file *, struct poll_table_struct *);long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);long (*compat_ioctl) (struct file *, unsigned int, unsigned long);int (*mmap) (struct file *, struct vm_area_struct *);unsigned long mmap_supported_flags;int (*open) (struct inode *, struct file *);int (*flush) (struct file *, fl_owner_t id);int (*release) (struct inode *, struct file *);int (*fsync) (struct file *, loff_t, loff_t, int datasync);int (*fasync) (int, struct file *, int);int (*lock) (struct file *, int, struct file_lock *);ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);int (*check_flags)(int);int (*flock) (struct file *, int, struct file_lock *);ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);int (*setlease)(struct file *, long, struct file_lock **, void **);long (*fallocate)(struct file *file, int mode, loff_t offset,loff_t len);void (*show_fdinfo)(struct seq_file *m, struct file *f);
#ifndef CONFIG_MMUunsigned (*mmap_capabilities)(struct file *);
#endifssize_t (*copy_file_range)(struct file *, loff_t, struct file *,loff_t, size_t, unsigned int);loff_t (*remap_file_range)(struct file *file_in, loff_t pos_in,struct file *file_out, loff_t pos_out,loff_t len, unsigned int remap_flags);int (*fadvise)(struct file *, loff_t, loff_t, int);
} __randomize_layout;

linux/fs.h中还定义了一个非常重要的结构体file:

struct file {union {struct llist_node       fu_llist;struct rcu_head         fu_rcuhead;} f_u;struct path             f_path;struct inode            *f_inode;       /* cached value */const struct file_operations    *f_op;/** Protects f_ep_links, f_flags.* Must not be taken from IRQ context.*/spinlock_t              f_lock;enum rw_hint            f_write_hint;atomic_long_t           f_count;unsigned int            f_flags;fmode_t                 f_mode;struct mutex            f_pos_lock;loff_t                  f_pos;struct fown_struct      f_owner;const struct cred       *f_cred;struct file_ra_state    f_ra;u64                     f_version;
#ifdef CONFIG_SECURITYvoid                    *f_security;
#endif/* needed for tty driver, and maybe others */void                    *private_data;#ifdef CONFIG_EPOLL/* Used by fs/eventpoll.c to link all the hooks to this file */struct list_head        f_ep_links;struct list_head        f_tfile_llink;
#endif /* #ifdef CONFIG_EPOLL */struct address_space    *f_mapping;errseq_t                f_wb_err;
} __randomize_layout__attribute__((aligned(4)));  /* lest something weird decides that 2 is OK */

file结构代表的是一个打开的文件(不限于设备驱动程序,linux中每个打开的文件在内核空间都有一个对应的file结构)这个file结构体在调用open函数时建立,并在close之后释放;
在内核源码中,用filp文件指针来指向file结构体;

以rcu为前缀的,是Linux提供的一种lockless机制,Read-copy Update,是rwlcok读写锁的强化版;和rwlcok不同的是,rcu在写入的时候也可以读;
它适用于读多写少的情况,允许多个进程对文件同时进行读操作,用rcu_read_lock()和rcu_read_unlock()这两个API来保持一个读者的RCU临界区.在该临界区内不允许发生上下文切换;
对于写操作的时候,需要先复制一份原来的文件的备份(copy),然后在对副本文件修改,当确保执行了rcu_read_unlock之后才能够去用副本去覆盖;
这个文章写的很好;
并且file结构体中还定义了指向inode结构体的指针f_inode

struct inode            *f_inode;

还有指向file_operation的指针f_op;

const struct file_operations    *f_op;

关于inode结构体:

linux用inode在内部表示文件,而前面提到的file是每打开一个文件就会建立一个file结构体,是打开文件的文件描述符; 对单个文件,可能会有许多个表示打开文件的文件描述符file结构,但他们都指向单个inode结构;

struct inode {umode_t			i_mode;unsigned short		i_opflags;kuid_t			i_uid;kgid_t			i_gid;unsigned int		i_flags;#ifdef CONFIG_FS_POSIX_ACLstruct posix_acl	*i_acl;struct posix_acl	*i_default_acl;
#endifconst struct inode_operations	*i_op;struct super_block	*i_sb;struct address_space	*i_mapping;#ifdef CONFIG_SECURITYvoid			*i_security;
#endif/* Stat data, not accessed from path walking */unsigned long		i_ino;/** Filesystems may only read i_nlink directly.  They shall use the* following functions for modification:**    (set|clear|inc|drop)_nlink*    inode_(inc|dec)_link_count*/union {const unsigned int i_nlink;unsigned int __i_nlink;};dev_t			i_rdev; loff_t			i_size;struct timespec64	i_atime;struct timespec64	i_mtime;struct timespec64	i_ctime;spinlock_t		i_lock;	/* i_blocks, i_bytes, maybe i_size */unsigned short          i_bytes;u8			i_blkbits;u8			i_write_hint;blkcnt_t		i_blocks;#ifdef __NEED_I_SIZE_ORDEREDseqcount_t		i_size_seqcount;
#endif/* Misc */unsigned long		i_state;struct rw_semaphore	i_rwsem;unsigned long		dirtied_when;	/* jiffies of first dirtying */unsigned long		dirtied_time_when;struct hlist_node	i_hash;struct list_head	i_io_list;	/* backing dev IO list */
#ifdef CONFIG_CGROUP_WRITEBACKstruct bdi_writeback	*i_wb;		/* the associated cgroup wb *//* foreign inode detection, see wbc_detach_inode() */int			i_wb_frn_winner;u16			i_wb_frn_avg_time;u16			i_wb_frn_history;
#endifstruct list_head	i_lru;		/* inode LRU list */struct list_head	i_sb_list;struct list_head	i_wb_list;	/* backing dev writeback list */union {struct hlist_head	i_dentry;struct rcu_head		i_rcu;};atomic64_t		i_version;atomic64_t		i_sequence; /* see futex */atomic_t		i_count;atomic_t		i_dio_count;atomic_t		i_writecount;
#if defined(CONFIG_IMA) || defined(CONFIG_FILE_LOCKING)atomic_t		i_readcount; /* struct files open RO */
#endifunion {const struct file_operations	*i_fop;	/* former ->i_op->default_file_ops */void (*free_inode)(struct inode *);};struct file_lock_context	*i_flctx;struct address_space	i_data;struct list_head	i_devices;union {struct pipe_inode_info	*i_pipe;struct block_device	*i_bdev;struct cdev		*i_cdev;char			*i_link;unsigned		i_dir_seq;};__u32			i_generation;#ifdef CONFIG_FSNOTIFY__u32			i_fsnotify_mask; /* all events this inode cares about */struct fsnotify_mark_connector __rcu	*i_fsnotify_marks;
#endif#ifdef CONFIG_FS_ENCRYPTIONstruct fscrypt_info	*i_crypt_info;
#endif#ifdef CONFIG_FS_VERITYstruct fsverity_info	*i_verity_info;
#endifvoid			*i_private; /* fs or device private pointer */
} __randomize_layout;

在indoe中定义了指向file_operations的指针i_fop

const struct file_operations	*i_fop;	/* former ->i_op->default_file_ops */

更多推荐

内核模块代码中的特性

本文发布于:2024-02-26 23:05:17,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1704305.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:内核   模块   特性   代码

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!