Re: 内核中如何调用用户态下的可执行程序? 我想在这里我们有一个误会, 就是这个问题的最初提法是内核如何调用一个应用程序, 而不是一个应用程序如何调用内核线程, 应用程序调用内核已经在前面说的很清楚了。 Re: 内核中如何调用用户态下的可执行程序? 我想其实也不要那么绝对,在内核中request_module()就是 调用用户进程insmod来加载module的。 Re: 内核中如何调用用户态下的可执行程序? do_signal()到用户态服务程序,在用户态服务程序里exec()执行你的ls. Re: 内核中如何调用用户态下的可执行程序? 网上交流,误会再所难免,请别介意。 Re: 内核中如何调用用户态下的可执行程序? 我承认我前面的论断有一些武断了,这个我查了内核源代码,实际情况是你所说的这样的,在 linux/init/main.c中就有这个很多的内核主动的调用应用程序 if (execute_command) execve(execute_command,argv_init,envp_init); execve("/sbin/init",argv_init,envp_init); execve("/etc/init",argv_init,envp_init); execve("/bin/init",argv_init,envp_init); execve("/bin/sh",argv_init,envp_init); 还有,由于你的提醒,我也找到了linux在启动rc.d的内容 也在同一个文件里 static int do_linuxrc(void * shell) { static char *argv[] = { "linuxrc", NULL, }; close(0);close(1);close(2); setsid(); (void) open("/dev/console",O_RDWR,0); (void) dup(0); (void) dup(0); return execve(shell, argv, envp_init); } 看来还是大家一起来讨论,才能共同进步 Re: 内核中如何调用用户态下的可执行程序? 对cpu来说用户态的指令和核心态的指令是公平的,当然这不包括核心态特权指令,但是这并不影响用它们构成“程序”。不要把“核心程序”和用户态程序当成完全不同的东西,对编译器来说核心也是“程序”。 Re: 内核中如何调用用户态下的可执行程序? 真的是错误么?作为信号的服务程序不是由内河来调用的么? Re: 内核中如何调用用户态下的可执行程序? 以前在2.2中实现过,但在softirq中(以前是底半)如果要执行的程序是阻塞的,会有一些问题 PS. 2.4中已经做了这么多包裹函数,比2.2强多了. ;-) Re: 内核中如何调用用户态下的可执行程序? 比如说我调试好了一个用户程序, 我想让它在某个外部中断来的时候,执行一下这个用户程序, 应该怎么做呢 ? 谢谢! Re: 内核中如何调用用户态下的可执行程序? 一个例子,call_usermodehelper的调用返回为0,但看不到执行结果。 #define __KERNEL__ #define MODULE #include <linux/kernel.h> #include <linux/module.h> #include <linux/sched.h> #include <linux/tty.h> #include <linux/kmod.h> #include <stdarg.h> void print_string(const char *fmt, ...) { struct tty_struct *my_tty; va_list args; char str[64]; va_start(args, fmt); vsprintf(str, fmt, args); va_end(args); my_tty = current->tty; if(my_tty != NULL) { (*(my_tty->driver).write)( my_tty, 0, str, strlen(str)); (*(my_tty->driver).write)( my_tty, 0, "/015/012", 2); } } void call_ps() { char *path = "/bin/ps"; char *envp[3]; char *argv[2]; int ret = 0; argv[0] = path; argv[1] = 0; envp[0] = "HOME=/"; envp[1] = "PATH = /bin"; envp[2] = 0; ret = call_usermodehelper(path, argv, envp); print_string("path = %s - ret = %d", path, ret); } int init_module(void) { call_ps(); return 0; } void cleanup_module(void) { return; } 在命令行上可以看到path = /bin/ps - ret = 0;但怎么没有看到ps 的执行结果
[最终结果]
看了以上讨论,最终用最后那哥们的方法试了一下,其实他已经实现,只不过输出不在当前的终端,或终端已经被重定向到其他虚拟终端,所以看不到输出,自己是抄了一些东西,实现了一下方法可以实现调用应用层程序。
#define __KERNEL__
#define MODULE
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <stdarg.h>
static int execute(const char *string)
{
int ret;
char *envp[] = {
"HOME=/",
"TERM=linux",
"PATH=/sbin:/usr/sbin:/bin:/usr/bin",
NULL,
};
char *argv[] = {
"/bin/bash",
"-c",
(char *)string,
NULL,
};
if ((ret =
call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC)) != 0) {
printk(KERN_ERR "run user application failed /"%s/": %i/n", string,
ret);
}
return ret;
}
struct tty_struct *my_tty; va_list args; char str[64]; va_start (args, fmt); vsprintf (str, fmt, args); va_end (args); my_tty = current->signal->tty; if (my_tty != NULL) { (*(my_tty->driver->ops)->write) (my_tty, str, strlen (str)); (*(my_tty->driver->ops)->write) (my_tty, "/015/012", 2); } } void int ret = 0; ret = execute("touch /tmp/nicaicai; echo haha > /tmp/nicaicai;"); } int call_execute (); return 0; } void return; }
void
print_string (const char *fmt, ...)
{
call_execute ()
{
init_module (void)
{
cleanup_module (void)
{
附上函数说明
call_usermodehelper()用来让内核空间的驱动程式启用用户空间的若干应用程式,
如:/sbin/hotplug、/bin/gliethttp_hello等,他的函数原型如下:
static inline int call_usermodehelper(char *path, char **argv, char **envp, enum umh_wait wait);
path --- 用户空间所要启用的应用程式路径,如:"/sbin/hotplug",那么hotplug应用程式就会被内核加载启用
argv --- 传递给启用了的用户空间应用程式的参数argv
envp --- 传递给启用了的用户空间应用程式的环境变量envp,类似int main(int argc, char *_argv[])模式
wait --- 调用call_usermodehelper的内核程式是否等到被exec的用户空间应用程式,如:"/sbin/hotplug"退出后,才继续执行.