使用call_usermodehelper在Linux内核中直接运行用户空间程序(二)

2014-11-24 09:19:48 · 作者: · 浏览: 1
wait;
406把用户空间进程挂到一个内核工作队列。
407 queue_work(khelper_wq, &sub_info->work);
408 if (wait == UMH_NO_WAIT) /* task has freed sub_info */
409 goto unlock;
如果等待子进程完成,那么执行等待完成的 事件通知和唤醒。就是说当前进程sleep。
410 wait_for_completion(&done);
411 retval = sub_info->retval;
412
413out:
414 call_usermodehelper_freeinfo(sub_info);
415unlock:
416 helper_unlock();
417 return retval;
418}
419EXPORT_SYMBOL(call_usermodehelper_exec);
420
421void __init usermodehelper_init(void)
422{
423 khelper_wq = create_singlethread_workqueue("khelper");
424 BUG_ON(!khelper_wq);
425}






call_usermodeheler函数创建的新程序实际上作为keventd内核线程的子进程运行,因此具有root权限。


新程序被扔到内核工作队列“khelper”中进行执行。


如果使用UMH_NO_WAIT,那么因为没有在事件队列上等待和唤醒的过程,因此可以在中断上下文中使用。


它的返回值是新程序的返回值。





#include<unistd.h>


intexecve(const char *filename, char *const argv[],
char*const
envp[]);


execve函数使用sys_execve系统调用,创建并运行一个程序。


argv是字符串数组,是将被传输到新程序的参数。


envp是字符串数组,格式是key=value,是传递给新程序的环境变量。


argvenvp都必须以NULL字符串结束。以此来实现对字符串数组的大小统计。






这就意味着,argv的第一个参数也必须是程序名。也就是说,新程序名要在execve函数的参数中传递两次。





这和main函数传入的参数格式也是一致的。








/*


============================================================================


Name : testDriver1.c


Author :Edward Shenshendl_s@hotmail.com


Version :


Copyright : Your copyrightnotice


Description : Hello World in C,Ansi-style


============================================================================


*/




#include


#include


#include


//#include




#include/*printk()*/


#include


MODULE_LICENSE("DualBSD/GPL");






static__initinttestDriver1_init(void){


intresult=0;


char cmdPath[]="/usr/bin/touch";


char* cmdArgv[]={cmdPath,"/touchX.txt",NULL};


char* cmdEnvp[]={"HOME=/",


"PATH=/sbin:/bin:/usr/bin",NULL};



result=call_usermodehelper(cmdPath,cmdArgv,cmdEnvp,UMH_WAIT_PROC);


printk(KERN_DEBUG"testDriver1_initexec!Theresult of call_usermodehelper is %d\n",result);



printk(KERN_DEBUG"testDriver1_initexec!Theprocess is \"%s\",pidis %d ,sys_getpid is %d \n",current->comm,current->pid);


returnresult;


}






static__exitvoidtestDriver1_exit(void){


intresult=0;


char cmdPath[]="/bin/rm";


char* cmdArgv[]={cmdPath,"/touchX.txt",NULL};


char* cmdEnvp[]={"HOME=/",


"PATH=/sbin:/bin:/usr/bin",NULL};



result=call_usermodehelper(cmdPath,cmdArgv,cmdEnvp,UMH_WAIT_PROC);


printk(KERN_DEBUG"testDriver1_exitexec!Theresult of call_usermodehelper is %d\n",result);


printk(KERN_DEBUG"testDriver1_exitexec!Theprocess is \"%s\",pidis %d \n",current->comm,current->pid);


}




module_init(testDriver1_init);


module_exit(testDriver1_exit);






编译上述模块的命令


make-C /lib/modules/`uname -r`/build M=`pwd` modules




然后使用insmodrmmod命令加载和卸载驱动。可以看到上述命令创建了文件和删除了创建的文件。