zoukankan      html  css  js  c++  java
  • fork和exec系统调用在内核中的执行过程

    一、编程实现一个简单的shell程序

    大体上,先fork()一个子进程, 然后在子进程里执行新程序,父进程则等待子进程执行结束。子进程的fork()返回0,父进程的fork()返回子进程的进程ID,以此可以区分两个进程。在子进程中通过调用execl来执行新程序,execl函数的签名为:

    int execl(const char * path, const char * arg, ...);

    为了调用"/bin/"中的程序,先定义一个路径字符串"/bin/",然后把新程序的名字拼接在后面,作为execl的第一个参数传入。后面是新程序的名称和它的一个参数,这里只支持给新程序最多一个参数。

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <string.h>
    
    int main(int argc, char *argv[])
    {
        pid_t pid;
        char path[255] = "/bin/";
        if ( (pid=fork()) == 0)
            execl(strcat(path, argv[1]), argv[1], argv[2], NULL);
        else
            wait(NULL);
        return 0;
    }

     将上述代码命名为myshell.c,然后gcc myshell.c -o myshell,然后执行./myshell echo hello,回显“hello”, 执行./myshell ls -l,显示当前目录下的详细文件信息。

    二、分析fork和exec系统调用在内核中的执行过程

    fork()系统调用其实封装的是do_fork()函数,du_fork()函数的是实现见这里1558行:http://lxr.free-electrons.com/source/kernel/fork.c,下面摘抄了一些重要的部分:

    long do_fork(unsigned long clone_flags,
                  unsigned long stack_start,
                  unsigned long stack_size,
                  int __user *parent_tidptr,
                  int __user *child_tidptr)
    {
    struct task_struct *p; ...... p
    = copy_process(clone_flags, stack_start, stack_size, child_tidptr, NULL, trace); if (!IS_ERR(p)) { ...... wake_up_new_task(p); /* forking complete and child started to run, tell ptracer */ ...... } else { nr = PTR_ERR(p); } return nr; }

    可见它先把父进程复制了一份,返回struct task_struct结构的一个指针,然后唤醒子进程,基本上就完成了一个fork过程。可见fork主要的工作就是创建一个新进程,然后把父进程的栈等内容复制过去。

    struct task_struct是进程控制块的结构,是进程最为重要的部分,里面定义有

    volatile long state; 进程状态

    unsigned int flags; 进程优先级

    struct mm_struct *mm; 进程的内存使用信息

    pid_t pid; 进程ID

    struct task_struct *parent;  指向父进程

    等等许多的信息。

    对于exec函数来说,它主要执行的函数是do_execve_common(),其定义见这里1453行:http://lxr.free-electrons.com/source/fs/exec.c

    这个函数先打开要执行的文件:

    file = open_exec(filename);

    然后初始化并填好struct linux_binprm *bprm;这个结构体,这个结构题的定义见这里:http://lxr.free-electrons.com/source/include/linux/binfmts.h

    struct linux_binprm {
            char buf[BINPRM_BUF_SIZE];
    #ifdef CONFIG_MMU
            struct vm_area_struct *vma;
            unsigned long vma_pages;
    #else
    # define MAX_ARG_PAGES  32
            struct page *page[MAX_ARG_PAGES];
    #endif
            struct mm_struct *mm;
            unsigned long p; /* current top of mem */
            unsigned int
                    cred_prepared:1,/* true if creds already prepared (multiple
                                     * preps happen for interpreters) */
                    cap_effective:1;/* true if has elevated effective capabilities,
                                     * false if not; except for init which inherits
                                     * its parent's caps anyway */
    #ifdef __alpha__
            unsigned int taso:1;
    #endif
            unsigned int recursion_depth;
            struct file * file;
            struct cred *cred;      /* new credentials */
            int unsafe;             /* how unsafe this exec is (mask of LSM_UNSAFE_*) */
            unsigned int per_clear; /* bits to clear in current->personality */
            int argc, envc;
            const char * filename;  /* Name of binary as seen by procps */
            const char * interp;    /* Name of the binary really executed. Most
                                       of the time same as filename, but could be
                                       different for binfmt_{misc,script} */
            unsigned interp_flags;
            unsigned interp_data;
            unsigned long loader, exec;
            char tcomm[TASK_COMM_LEN];
    };

    其第一个buf变量用来保存可执行文件的头128字节,page指针数组保存所用的页面,file指针则指向了要执行的文件。

    填好bprm后,do_execve_common()接下来做了一件非常重要的事,就是调用search_binary_handler(),这个函数中会调用本文件全局变量formats的每一个load_binary()函数,来把elf文件读到内存中。这样,exec基本上就完成了。

    
    
  • 相关阅读:
    股票交易接口
    股票自动买卖
    安信证券接口的demo做得不好。
    MEF bug? 无法加载外部的DLL
    如何移植行情软件的指标到千发股票自动交易软件?
    股票策略交易
    博客园自动关注病毒 只活了一小会儿。
    Float 运算的怪异性
    文件大小和占用空间为何不一样
    做最好的自己
  • 原文地址:https://www.cnblogs.com/yding9/p/3109408.html
Copyright © 2011-2022 走看看