⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 module.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 2 页
字号:
		    && !__MOD_IN_USE(mod)) {			if ((mod->flags & MOD_VISITED)			    && !(mod->flags & MOD_JUST_FREED)) {				spin_unlock(&unload_lock);				mod->flags &= ~MOD_VISITED;			} else {				mod->flags |= MOD_DELETED;				spin_unlock(&unload_lock);				free_module(mod, 1);				something_changed = 1;			}		} else {			spin_unlock(&unload_lock);		}	}		if (something_changed)		goto restart;			for (mod = module_list; mod != &kernel_module; mod = mod->next)		mod->flags &= ~MOD_JUST_FREED;		error = 0;out:	unlock_kernel();	return error;}/* Query various bits about modules.  */static intqm_modules(char *buf, size_t bufsize, size_t *ret){	struct module *mod;	size_t nmod, space, len;	nmod = space = 0;	for (mod=module_list; mod != &kernel_module; mod=mod->next, ++nmod) {		len = strlen(mod->name)+1;		if (len > bufsize)			goto calc_space_needed;		if (copy_to_user(buf, mod->name, len))			return -EFAULT;		buf += len;		bufsize -= len;		space += len;	}	if (put_user(nmod, ret))		return -EFAULT;	else		return 0;calc_space_needed:	space += len;	while ((mod = mod->next) != &kernel_module)		space += strlen(mod->name)+1;	if (put_user(space, ret))		return -EFAULT;	else		return -ENOSPC;}static intqm_deps(struct module *mod, char *buf, size_t bufsize, size_t *ret){	size_t i, space, len;	if (mod == &kernel_module)		return -EINVAL;	if (!MOD_CAN_QUERY(mod))		if (put_user(0, ret))			return -EFAULT;		else			return 0;	space = 0;	for (i = 0; i < mod->ndeps; ++i) {		const char *dep_name = mod->deps[i].dep->name;		len = strlen(dep_name)+1;		if (len > bufsize)			goto calc_space_needed;		if (copy_to_user(buf, dep_name, len))			return -EFAULT;		buf += len;		bufsize -= len;		space += len;	}	if (put_user(i, ret))		return -EFAULT;	else		return 0;calc_space_needed:	space += len;	while (++i < mod->ndeps)		space += strlen(mod->deps[i].dep->name)+1;	if (put_user(space, ret))		return -EFAULT;	else		return -ENOSPC;}static intqm_refs(struct module *mod, char *buf, size_t bufsize, size_t *ret){	size_t nrefs, space, len;	struct module_ref *ref;	if (mod == &kernel_module)		return -EINVAL;	if (!MOD_CAN_QUERY(mod))		if (put_user(0, ret))			return -EFAULT;		else			return 0;	space = 0;	for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) {		const char *ref_name = ref->ref->name;		len = strlen(ref_name)+1;		if (len > bufsize)			goto calc_space_needed;		if (copy_to_user(buf, ref_name, len))			return -EFAULT;		buf += len;		bufsize -= len;		space += len;	}	if (put_user(nrefs, ret))		return -EFAULT;	else		return 0;calc_space_needed:	space += len;	while ((ref = ref->next_ref) != NULL)		space += strlen(ref->ref->name)+1;	if (put_user(space, ret))		return -EFAULT;	else		return -ENOSPC;}static intqm_symbols(struct module *mod, char *buf, size_t bufsize, size_t *ret){	size_t i, space, len;	struct module_symbol *s;	char *strings;	unsigned long *vals;	if (!MOD_CAN_QUERY(mod))		if (put_user(0, ret))			return -EFAULT;		else			return 0;	space = mod->nsyms * 2*sizeof(void *);	i = len = 0;	s = mod->syms;	if (space > bufsize)		goto calc_space_needed;	if (!access_ok(VERIFY_WRITE, buf, space))		return -EFAULT;	bufsize -= space;	vals = (unsigned long *)buf;	strings = buf+space;	for (; i < mod->nsyms ; ++i, ++s, vals += 2) {		len = strlen(s->name)+1;		if (len > bufsize)			goto calc_space_needed;		if (copy_to_user(strings, s->name, len)		    || __put_user(s->value, vals+0)		    || __put_user(space, vals+1))			return -EFAULT;		strings += len;		bufsize -= len;		space += len;	}	if (put_user(i, ret))		return -EFAULT;	else		return 0;calc_space_needed:	for (; i < mod->nsyms; ++i, ++s)		space += strlen(s->name)+1;	if (put_user(space, ret))		return -EFAULT;	else		return -ENOSPC;}static intqm_info(struct module *mod, char *buf, size_t bufsize, size_t *ret){	int error = 0;	if (mod == &kernel_module)		return -EINVAL;	if (sizeof(struct module_info) <= bufsize) {		struct module_info info;		info.addr = (unsigned long)mod;		info.size = mod->size;		info.flags = mod->flags;				/* usecount is one too high here - report appropriately to		   compensate for locking */		info.usecount = (mod_member_present(mod, can_unload)				 && mod->can_unload ? -1 : atomic_read(&mod->uc.usecount)-1);		if (copy_to_user(buf, &info, sizeof(struct module_info)))			return -EFAULT;	} else		error = -ENOSPC;	if (put_user(sizeof(struct module_info), ret))		return -EFAULT;	return error;}asmlinkage longsys_query_module(const char *name_user, int which, char *buf, size_t bufsize,		 size_t *ret){	struct module *mod;	int err;	lock_kernel();	if (name_user == NULL)		mod = &kernel_module;	else {		long namelen;		char *name;		if ((namelen = get_mod_name(name_user, &name)) < 0) {			err = namelen;			goto out;		}		err = -ENOENT;		if ((mod = find_module(name)) == NULL) {			put_mod_name(name);			goto out;		}		put_mod_name(name);	}	/* __MOD_ touches the flags. We must avoid that */		atomic_inc(&mod->uc.usecount);			switch (which)	{	case 0:		err = 0;		break;	case QM_MODULES:		err = qm_modules(buf, bufsize, ret);		break;	case QM_DEPS:		err = qm_deps(mod, buf, bufsize, ret);		break;	case QM_REFS:		err = qm_refs(mod, buf, bufsize, ret);		break;	case QM_SYMBOLS:		err = qm_symbols(mod, buf, bufsize, ret);		break;	case QM_INFO:		err = qm_info(mod, buf, bufsize, ret);		break;	default:		err = -EINVAL;		break;	}	atomic_dec(&mod->uc.usecount);	out:	unlock_kernel();	return err;}/* * Copy the kernel symbol table to user space.  If the argument is * NULL, just return the size of the table. * * This call is obsolete.  New programs should use query_module+QM_SYMBOLS * which does not arbitrarily limit the length of symbols. */asmlinkage longsys_get_kernel_syms(struct kernel_sym *table){	struct module *mod;	int i;	struct kernel_sym ksym;	lock_kernel();	for (mod = module_list, i = 0; mod; mod = mod->next) {		/* include the count for the module name! */		i += mod->nsyms + 1;	}	if (table == NULL)		goto out;	/* So that we don't give the user our stack content */	memset (&ksym, 0, sizeof (ksym));	for (mod = module_list, i = 0; mod; mod = mod->next) {		struct module_symbol *msym;		unsigned int j;		if (!MOD_CAN_QUERY(mod))			continue;		/* magic: write module info as a pseudo symbol */		ksym.value = (unsigned long)mod;		ksym.name[0] = '#';		strncpy(ksym.name+1, mod->name, sizeof(ksym.name)-1);		ksym.name[sizeof(ksym.name)-1] = '\0';		if (copy_to_user(table, &ksym, sizeof(ksym)) != 0)			goto out;		++i, ++table;		if (mod->nsyms == 0)			continue;		for (j = 0, msym = mod->syms; j < mod->nsyms; ++j, ++msym) {			ksym.value = msym->value;			strncpy(ksym.name, msym->name, sizeof(ksym.name));			ksym.name[sizeof(ksym.name)-1] = '\0';			if (copy_to_user(table, &ksym, sizeof(ksym)) != 0)				goto out;			++i, ++table;		}	}out:	unlock_kernel();	return i;}/* * Look for a module by name, ignoring modules marked for deletion. */struct module *find_module(const char *name){	struct module *mod;	for (mod = module_list; mod ; mod = mod->next) {		if (mod->flags & MOD_DELETED)			continue;		if (!strcmp(mod->name, name))			break;	}	return mod;}/* * Free the given module. */voidfree_module(struct module *mod, int tag_freed){	struct module_ref *dep;	unsigned i;	unsigned long flags;	/* Let the module clean up.  */	if (mod->flags & MOD_RUNNING)	{		if(mod->cleanup)			mod->cleanup();		mod->flags &= ~MOD_RUNNING;	}	/* Remove the module from the dependency lists.  */	for (i = 0, dep = mod->deps; i < mod->ndeps; ++i, ++dep) {		struct module_ref **pp;		for (pp = &dep->dep->refs; *pp != dep; pp = &(*pp)->next_ref)			continue;		*pp = dep->next_ref;		if (tag_freed && dep->dep->refs == NULL)			dep->dep->flags |= MOD_JUST_FREED;	}	/* And from the main module list.  */	spin_lock_irqsave(&modlist_lock, flags);	if (mod == module_list) {		module_list = mod->next;	} else {		struct module *p;		for (p = module_list; p->next != mod; p = p->next)			continue;		p->next = mod->next;	}	spin_unlock_irqrestore(&modlist_lock, flags);	/* And free the memory.  */	module_unmap(mod);}/* * Called by the /proc file system to return a current list of modules. */int get_module_list(char *p){	size_t left = PAGE_SIZE;	struct module *mod;	char tmpstr[64];	struct module_ref *ref;	for (mod = module_list; mod != &kernel_module; mod = mod->next) {		long len;		const char *q;#define safe_copy_str(str, len)						\		do {							\			if (left < len)					\				goto fini;				\			memcpy(p, str, len); p += len, left -= len;	\		} while (0)#define safe_copy_cstr(str)	safe_copy_str(str, sizeof(str)-1)		len = strlen(mod->name);		safe_copy_str(mod->name, len);		if ((len = 20 - len) > 0) {			if (left < len)				goto fini;			memset(p, ' ', len);			p += len;			left -= len;		}		len = sprintf(tmpstr, "%8lu", mod->size);		safe_copy_str(tmpstr, len);		if (mod->flags & MOD_RUNNING) {			len = sprintf(tmpstr, "%4ld",				      (mod_member_present(mod, can_unload)				       && mod->can_unload				       ? -1L : (long)atomic_read(&mod->uc.usecount)));			safe_copy_str(tmpstr, len);		}		if (mod->flags & MOD_DELETED)			safe_copy_cstr(" (deleted)");		else if (mod->flags & MOD_RUNNING) {			if (mod->flags & MOD_AUTOCLEAN)				safe_copy_cstr(" (autoclean)");			if (!(mod->flags & MOD_USED_ONCE))				safe_copy_cstr(" (unused)");		}		else if (mod->flags & MOD_INITIALIZING)			safe_copy_cstr(" (initializing)");		else			safe_copy_cstr(" (uninitialized)");		if ((ref = mod->refs) != NULL) {			safe_copy_cstr(" [");			while (1) {				q = ref->ref->name;				len = strlen(q);				safe_copy_str(q, len);				if ((ref = ref->next_ref) != NULL)					safe_copy_cstr(" ");				else					break;			}			safe_copy_cstr("]");		}		safe_copy_cstr("\n");#undef safe_copy_str#undef safe_copy_cstr	}fini:	return PAGE_SIZE - left;}/* * Called by the /proc file system to return a current list of ksyms. */struct mod_sym {	struct module *mod;	int index;};/* iterator */static void *s_start(struct seq_file *m, loff_t *pos){	struct mod_sym *p = kmalloc(sizeof(*p), GFP_KERNEL);	struct module *v;	loff_t n = *pos;	if (!p)		return ERR_PTR(-ENOMEM);	lock_kernel();	for (v = module_list, n = *pos; v; n -= v->nsyms, v = v->next) {		if (n < v->nsyms) {			p->mod = v;			p->index = n;			return p;		}	}	unlock_kernel();	kfree(p);	return NULL;}static void *s_next(struct seq_file *m, void *p, loff_t *pos){	struct mod_sym *v = p;	(*pos)++;	if (++v->index >= v->mod->nsyms) {		do {			v->mod = v->mod->next;			if (!v->mod) {				unlock_kernel();				kfree(p);				return NULL;			}		} while (!v->mod->nsyms);		v->index = 0;	}	return p;}static void s_stop(struct seq_file *m, void *p){	if (p && !IS_ERR(p)) {		unlock_kernel();		kfree(p);	}}static int s_show(struct seq_file *m, void *p){	struct mod_sym *v = p;	struct module_symbol *sym;	if (!MOD_CAN_QUERY(v->mod))		return 0;	sym = &v->mod->syms[v->index];	if (*v->mod->name)		seq_printf(m, "%0*lx %s\t[%s]\n", (int)(2*sizeof(void*)),			       sym->value, sym->name, v->mod->name);	else		seq_printf(m, "%0*lx %s\n", (int)(2*sizeof(void*)),			       sym->value, sym->name);	return 0;}struct seq_operations ksyms_op = {	start:	s_start,	next:	s_next,	stop:	s_stop,	show:	s_show};#else		/* CONFIG_MODULES *//* Dummy syscalls for people who don't want modules */asmlinkage unsigned longsys_create_module(const char *name_user, size_t size){	return -ENOSYS;}asmlinkage longsys_init_module(const char *name_user, struct module *mod_user){	return -ENOSYS;}asmlinkage longsys_delete_module(const char *name_user){	return -ENOSYS;}asmlinkage longsys_query_module(const char *name_user, int which, char *buf, size_t bufsize,		 size_t *ret){	/* Let the program know about the new interface.  Not that	   it'll do them much good.  */	if (which == 0)		return 0;	return -ENOSYS;}asmlinkage longsys_get_kernel_syms(struct kernel_sym *table){	return -ENOSYS;}int try_inc_mod_count(struct module *mod){	return 1;}#endif	/* CONFIG_MODULES */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -