内核启动用户态的应用程序是通过call_usermodehelper来调用的,比较常见的调用,比如modprobe.
static inline int
call_usermodehelper(char *path, char **argv, char **envp, enum umh_wait wait)
参数说明;
path : 应用程序的位置
argv : 传递给用户态应用程序的参数
envp: 传递给应用程序的环境变量
wait : 调用用户态应用程序的内核程序是否等到用户态程序退出后才退出。
使用的例子:
我们来看kmod.c的源码,它通过调用用户态的modprobe来加载所需要的驱动模块。
int request_module(const char *fmt, ...)
{
va_list args;
char module_name[MODULE_NAME_LEN];
unsigned int max_modprobes;
int ret;
///构造传递给modeprobe的参数
char *argv[] = { modprobe_path, "-q", "--", module_name, NULL };
static char *envp[] = { "HOME=/",
"TERM=linux",
"PATH=/sbin:/usr/sbin:/bin:/usr/bin",
NULL };
static atomic_t kmod_concurrent = ATOMIC_INIT(0);
#define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */
static int kmod_loop_msg;
va_start(args, fmt);
ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args);
va_end(args);
if (ret >= MODULE_NAME_LEN)
return -ENAMETOOLONG;
/* If modprobe needs a service that is in a module, we get a recursive
* loop. Limit the number of running kmod threads to max_threads/2 or
* MAX_KMOD_CONCURRENT, whichever is the smaller. A cleaner method
* would be to run the parents of this process, counting how many times
* kmod was invoked. That would mean accessing the internals of the
* process tables to get the command line, proc_pid_cmdline is static
* and it is not worth changing the proc code just to handle this case.
* KAO.
*
* "trace the ppid" is simple, but will fail if someone's
* parent exits. I think this is as good as it gets. --RR
*/
max_modprobes = min(max_threads/2, MAX_KMOD_CONCURRENT);
atomic_inc(&kmod_concurrent);
if (atomic_read(&kmod_concurrent) > max_modprobes) {
/* We may be blaming an innocent here, but unlikely */
if (kmod_loop_msg++ < 5)
printk(KERN_ERR
"request_module: runaway loop modprobe %s\n",
module_name);
atomic_dec(&kmod_concurrent);
return -ENOMEM;
}
///调用modeprobe.
ret = call_usermodehelper(modprobe_path, argv, envp, 1);
atomic_dec(&kmod_concurrent);
return ret;
}
分享到:
相关推荐
在传统的通信方式中,内核与用户态之间的交互往往需要用户启动内核线程,这会带来额外的开销。而Netlink通过软中断技术,可以在不启动内核线程的情况下接收用户空间的数据,提高了通信效率和实时性。当通信的两端都...
虚拟化技术可以创建多个隔离的虚拟环境,使得同一系统上可以运行不同的内核和用户态程序。虚拟化不仅提高了内核用户态交互的灵活性,还允许不同的进程并行执行。 #### 可信计算技术机制与应用 **3.1 可信计算技术...
完成上述步骤后,内核已经准备好启动第一个用户态进程。通常情况下,这个进程是 `init` 或者 `systemd`(在较新的系统中),它们负责启动其他系统服务和应用程序。 1. **启动init或systemd**:通过 `execve` 系统调...
【计算机操作系统实验 - 运行用户态程序】 本实验主要关注的是操作系统中用户态程序的加载与执行,涉及的操作系统理论和技术主要包括操作系统架构、进程管理、内存管理和虚拟内存。以下是对实验内容的详细解释: ...
本实验主要目标是在GeekOS系统中实现用户态程序的加载与运行,这将深入理解操作系统内核与用户程序之间的交互。 实验要求我们按照指定的设计,编写代码来实现在用户态模式下加载并运行可执行程序。实验的关键在于...
在Windows操作系统中,用户态程序高效排错是一个关键的技能,尤其对于软件开发者和系统管理员来说,能够快速定位和解决问题是提升工作效率的关键。本压缩包文件"Windows用户态程序高效排错(01-02).rar"可能包含了两...
在Linux 0.11中,当发生中断或系统调用时,控制权会从用户态转移到内核态,此时进程的堆栈会切换到内核态堆栈,以保护用户空间的完整性。 要观察内核态堆栈,可以使用内核调试工具,如gdb(GNU调试器)或在Bochs的...
【操作系统实验:运行用户态程序】 本实验主要探讨如何在操作系统环境下,特别是在GeekOS系统中,实现用户态程序的加载与运行。实验的核心在于理解操作系统如何管理进程、内存分配以及用户态与内核态之间的切换。...
本实验主要涉及的操作系统知识点集中在用户态程序的加载与运行,以及与之相关的内存管理和进程管理。以下是对这些概念的详细说明: 1. **用户态与内核态**: 计算机操作系统通常有内核态和用户态两种运行模式。在...
Sysfs 是一个基于内存的文件系统,实际上它基于 ramfs,sysfs 提供了一种把内核数据结构,它们的属性以及属性与数据结构的联系开放给用户态的方式,它与 kobject 子系统紧密地结合在一起,因此内核开发者不需要直接...
实验目标是掌握GeekOS系统中加载和运行用户态程序的方法。学生需要按照实验讲义P127页的设计要求,实现相关代码,并能够解释用户程序参数的传递方式。实验内容主要涉及以下几个文件的修改: 1. 修改`src/GeekOS/...
在Windows操作系统环境中,调试用户态程序是一项至关重要的技能,尤其对于开发者和系统管理员而言。"Windows用户态程序高效排错"的主题涵盖了如何有效地诊断和解决应用程序中的错误和异常。在这个过程中,我们通常会...
本课程从理解计算机硬件的核心工作机制(存储程序计算机和函数调用堆栈)和用户态程序如何通过系统调用陷入内核(中断异常)入手,通过上下两个方向双向夹击的策略,并利用实际可运行程序的反汇编代码从实践的角度...
本文档主要探讨了一种名为“动态感染”的...通过这一系列的学习,读者不仅可以了解内核态下的程序保护机制,还能接触到内核态和用户态代码的混合编写,这对于深入理解操作系统的工作原理和提升安全防护能力大有裨益。
当用户态程序试图执行特权指令或调用系统调用时,会发生异常,使得CPU进入内核态执行相应操作。 通过这份课件的学习,可以深入理解Linux内核的基本架构和主要功能,对于操作系统原理和Linux系统编程有重要指导作用...
1. **内核启动参数**和**模块参数**允许在系统启动或加载模块时传递参数。 2. **sysfs**和**sysctl**接口允许动态配置内核参数。 3. **系统调用**是最直接的内核与用户态通信方式,通过定义新的系统调用来传递数据。...
3. **设置程序计数器**:将 PC 设置为内核中特定函数的地址,该函数将负责启动用户态进程。 4. **启动用户态进程**:通过调用 `fork()` 或类似函数创建用户态进程。 #### 结论 通过对 Linux 内核启动过程的深入...
3. **库函数使用**:由于驱动程序运行在内核态,因此不能直接使用标准C库等用户态库函数。 #### 八、用户态与内核态 - **用户态**:应用程序运行的状态,应用程序只能访问受限的系统资源。 - **内核态**:内核运行...