시스템 초기화 시kernel시스템 초기화를 완성하기 위해 내장 상태에서 프로그램을 만들고 실행합니다.

18424 단어
시스템 초기화 시kernelinit는 시스템 초기화를 완성하기 위해 내장 상태에서 프로그램을 만들고 실행합니다.내부 핵이 막 시작되었을 때 내부 핵 상태의 코드만 있었고 나중에 init 과정에서 내부 핵 상태에서 시스템을 초기화하는 프로그램을 실행해야만 사용자 공간에서 작업하는 프로세스가 생겼다.
/* 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 명령을 사용하여 드라이브를 불러오고 마운트합니다.위의 명령이 파일을 만들고 삭제한 것을 볼 수 있습니다.

좋은 웹페이지 즐겨찾기