시스템 초기화 시kernel시스템 초기화를 완성하기 위해 내장 상태에서 프로그램을 만들고 실행합니다.
/* This is a non __init function. Force it to be noinline otherwise gcc
736 * makes it inline to init() and it becomes part of init.text section
737 */
738static noinline int init_post(void)
739{
740 /* need to finish all async __init code before freeing the memory */
741 async_synchronize_full();
742 free_initmem();
743 mark_rodata_ro();
744 system_state = SYSTEM_RUNNING;
745 numa_default_policy();
746
747
748 current->signal->flags |= SIGNAL_UNKILLABLE;
749
750 if (ramdisk_execute_command) {
751 run_init_process(ramdisk_execute_command);
752 printk(KERN_WARNING "Failed to execute %s
",
753 ramdisk_execute_command);
754 }
755
756 /*
757 * We try each of these until one succeeds.
758 *
759 * The Bourne shell can be used instead of init if we are
760 * trying to recover a really broken machine.
커널에서 시스템 호출을 시작하여 사용자 공간을 실행하는 응용 프로그램입니다.이 프로그램들은 자동으로 루트 권한으로 실행됩니다.
761 */
762 if (execute_command) {
763 run_init_process(execute_command);
764 printk(KERN_WARNING "Failed to execute %s. Attempting "
765 "defaults...
", execute_command);
766 }
767 run_init_process("/sbin/init");
768 run_init_process("/etc/init");
769 run_init_process("/bin/init");
770 run_init_process("/bin/sh");
771
772 panic("No init found. Try passing init= option to kernel. "
773 "See Linux Documentation/init.txt for guidance.");
774}
여기에서 내부 핵은 이로써 사용자 공간 프로그램을 실행하여 첫 번째와 후속적인 사용자 공간 프로그램을 만들었다.일반 사용자 공간의 init 프로그램은 사용자가 시스템에 로그인할 수 있도록 셸을 시작합니다.이렇게 하면 이곳에서 시작된 사용자 공간의 프로그램은 영원히 되돌아오지 않을 것이다.정상적인 상황에서는 패닉에 이르지 않는다는 얘기다.시스템이 여기까지 실행되면 Linux Kernel의 초기화가 완료됩니다.이 때, 드라이브를 중단하고 중단하는 프로세스 스케줄링 메커니즘은 각 라인이 각 CPU에서 운행하도록 스케줄링한다.인터럽트 처리 프로그램이 때때로 터치됩니다.운영체제에서 일부 내부 핵 라인은 내부 핵 상태에서 운행하는데, 그들은 영원히 사용자 상태에 들어가지 않을 것이다.그것들도 사용자 상태의 메모리 공간이 아예 없다.그것의 선형 주소 공간은 내부 핵을 공유하는 선형 주소 공간이다.일부 사용자 프로세스는 보통 사용자 상태에서 실행된다.때때로 시스템 호출로 인해 내부 핵 상태에 들어가서 내부 핵이 제공하는 시스템 호출 처리 함수를 호출한다.
그러나 때때로, 우리의 내장 모듈이나 내장 라인은 사용자 공간의 프로세스를 호출하기를 희망한다. 예를 들어 시스템이 시작된 초기 initpost 함수 그렇게.
예를 들어, 하나의 드라이브가 내부 핵에서 주종 장치 번호를 얻은 후에, 사용자가 이 장치를 호출할 수 있도록 mknod 명령을 사용하여 해당하는 장치 파일을 만들어야 한다.
예를 들어 내부 라인이 특권이 있는 뒷문 프로그램을 쥐도 새도 모르게 몰래 실행하려고 한다.등등 이런 수요.
call_usermodehelper 함수
Linux Kernel이 제공하는 call사용자 공간 프로그램을 호스트에서 직접 만들고 실행할 수 있으며 루트 권한이 있습니다.
call_usermodehelper 함수 소스
include/linux/kmod.h 헤더 파일
105static inline int
106call_usermodehelper(char *path, char **argv, char **envp, enum umh_wait wait)
107{
108 return call_usermodehelper_fns(path, argv, envp, wait,
109 NULL, NULL, NULL);
110}
111
50enum umh_wait {
51 UMH_NO_WAIT = -1, /* don't wait at all */
52 UMH_WAIT_EXEC = 0, /* wait for the exec, but not the process */
53 UMH_WAIT_PROC = 1, /* wait for the process to complete */
54};
55
56struct subprocess_info {
57 struct work_struct work;
58 struct completion *complete;
59 char *path;
60 char **argv;
61 char **envp;
62 enum umh_wait wait;
63 int retval;
64 int (*init)(struct subprocess_info *info);
65 void (*cleanup)(struct subprocess_info *info);
66 void *data;
67};
68
kernel/kmod.c
377/**
378 * call_usermodehelper_exec - start a usermode application
379 * @sub_info: information about the subprocessa
380 * @wait: wait for the application to finish and return status. , 。
381 * when -1 don't wait at all, but you get no useful error back when
382 * the program couldn't be exec'ed. This makes it safe to call
383 * from interrupt context.
-1은 하위 프로세스가 끝날 때까지 기다리지 않음을 나타냅니다.이렇게 하면 프로그램 오류를 처리할 수 없습니다.중단된 상하문을 사용하려면 -1을 사용해야 한다.
384 *
385 * Runs a user-space application. The application is started
386 * asynchronously if wait is not set, and runs as a child of keventd.
387 * (ie. it runs with full root capabilities).
call_usermodehelper_exec 함수, 사용자 모드 프로그램을 시작합니다.wait를 설정하지 않으면 사용자 공간 프로그램이 비동기적으로 시작됩니다.이것은 루트 권한 아래에서 실행됩니다.keventd 프로세스의 하위 프로세스입니다.
388 */
389int call_usermodehelper_exec(struct subprocess_info *sub_info,
390 enum umh_wait wait)
391{
392 DECLARE_COMPLETION_ONSTACK(done);
393 int retval = 0;
394
395 helper_lock();
396 if (sub_info->path[0] == '\0')
397 goto out;
398
399 if (!khelper_wq || usermodehelper_disabled) {
400 retval = -EBUSY;
401 goto out;
402 }
403
404 sub_info->complete = &done;
405 sub_info->wait = wait;
406 。
407 queue_work(khelper_wq, &sub_info->work);
408 if (wait == UMH_NO_WAIT) /* task has freed sub_info */
409 goto unlock;
하위 프로세스가 완료되기를 기다리면 완료를 기다리는 이벤트 알림과 깨우기를 실행합니다.즉, 현재 프로세스 슬라이드입니다.
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_사용자modeheler 함수로 만든 새 프로그램은keventd 엔드 라인의 하위 프로세스로 실행되기 때문에 루트 권한이 있습니다.새 프로그램은 커널 작업 대기열 "khelper"에 던져져 실행됩니다.
UMHNO_WAIT는 이벤트 대기열에서 대기하고 깨우는 과정이 없기 때문에 인터럽트 상하문에서 사용할 수 있습니다.그것의 반환 값은 새 프로그램의 반환 값입니다.
call_usermodeheler 함수의 매개 변수 사용법은execve 함수와 일치합니다
#include
intexecve(const char *filename, char *const argv[], char*const envp[]);
execve 함수 사용sysexecve 시스템이 호출되어 프로그램을 만들고 실행합니다.
argv는 문자열 그룹입니다. 새 프로그램으로 전송될 인자입니다.
envp는 문자열 그룹이고, 형식은 키=value이며, 새 프로그램에 전달되는 환경 변수입니다.
argv와 envp 모두 NULL 문자열로 끝나야 합니다.문자열 그룹의 크기 통계를 실현합니다.
이것은argv의 첫 번째 매개 변수도 반드시 프로그램 이름이어야 한다는 것을 의미한다.새 프로그램 이름은execve 함수의 매개 변수에서 두 번 전달해야 한다는 뜻이다.
이것은main 함수가 전송하는 매개 변수 형식과도 일치합니다.
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
//#include<linux/config.h>
#include <linux/kernel.h>/*printk()*/
#include <linux/sched.h>
MODULE_LICENSE("GPL");
static __init int test_driver_init(void)
{
int result = 0;
char cmd_path[] = "/usr/bin/touch";
char* cmd_argv[] = {cmd_path,"/touchX.txt",NULL};
char* cmd_envp[] = {"HOME=/", "PATH=/sbin:/bin:/usr/bin", NULL};
result = call_usermodehelper(cmd_path, cmd_argv, cmd_envp, UMH_WAIT_PROC);
printk(KERN_DEBUG "test driver init exec! there result of call_usermodehelper is %d
", result);
printk(KERN_DEBUG "test driver init exec! the process is \"%s\", pid is %d.
",current->comm, current->pid);
return result;
}
static __exit void test_driver_exit(void)
{
int result = 0;
char cmd_path[] = "/bin/rm";
char* cmd_argv[] = {cmd_path,"/touchX.txt",NULL};
char* cmd_envp[] = {"HOME=/", "PATH=/sbin:/bin:/usr/bin", NULL};
result = call_usermodehelper(cmd_path, cmd_argv, cmd_envp, UMH_WAIT_PROC);
printk(KERN_DEBUG "test driver exit exec! the result of call_usermodehelper is %d
", result);
printk(KERN_DEBUG "test driver exit exec! the process is \"%s\",pidis %d
", current->comm, current->pid);
}
module_init(test_driver_init);
module_exit(test_driver_exit);
위 모듈의 명령을 컴파일합니다.
make-C/lib/modules/`uname -r`/build M=`pwd` modules
그리고 insmod와 rmmod 명령을 사용하여 드라이브를 불러오고 마운트합니다.위의 명령이 파일을 만들고 삭제한 것을 볼 수 있습니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.