zoukankan      html  css  js  c++  java
  • fork和vfork,exec

    一.fork:子进程是父进程的一个拷贝,子进程获得同父进程相同的数据,但是同父进程使用不同的数据段和堆栈段。

    特点:调用一次,返回两次。成功则在父进程中返回子进程ID,在子进程中返回0。失败则返回-1。

    返回后都执行fork之后的语句。

    例如:创建4个子进程,每个子进程都输出自己的pid和父进程的pid

    #include <stdio.h>
    #include <unistd.h>
    int main()
    {
        int pid ;
        for(int i = 0;i < 4;i++)
        {
            pid = fork();
            if(pid == 0) break;
        }
        if(pid == 0)
        {
            printf("i am child mypid:%d,myparentpid:%d
    ",getpid(),getppid());
        }else if(pid > 0)
        {
            printf("i am parent mypid:%d,myparentpid:%d
    ",getpid(),getppid());
            while(1);
        }
        else
        {
         perror(
    "call fork failed ");
          exit(1);
      }
    }

    在for循环中我们要判断是否为子进程,是子进程的话要跳出。因为子进程将父进程的i值拷贝过来,然后从fork语句的下一句开始执行。即}就会继续创建子进程,直到系统满了才停止。

    运行结果:

    父进程和子进程的输出顺序时可以变化的

    我们可以看到父进程的pid是bash,这个问题我们下面再讨论。

    二.vfork 和exec

    vfork 系统调用创建的进程共享其父进程的内存地址空间,但是并不完全复制父进程的数据段,而是和父进程共享其数据段。为了防止父进程重写子进程需要的数据,父进程会被 vfork 调用阻塞,直到子进程退出或执行一个新的程序。由于调用 vfork 函数时父进程被挂起,所以如果我们使用 vfork 函数替换 forkdemo 中的 fork 函数,那么执行程序时输出信息的顺序就不会变化了。

     exec:调用exec后,不会执行程序之后的代码。

    exec不创建新的程序

    #include <unistd.h>

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

        int execlp(const char *file, const char *arg, ...);

        int execle(const char *path, const char *arg, ..., char *const envp[]);

        int execv(const char *path, char *const argv[]);

        int execvp(const char *file, char *const argv[]);

        int execve(const char *path, char *const argv[], char *const envp[]);

    execve才是真正的系统调用  ,其他的函数都是调用它执行。

    如果调用成功则加载新的程序从启动代码开始执行,不再返回,如果调用出错则返回-1,所以exec函数只有出错的返回值而没有成功的返回值.

    函数名虽然看起来难记,但每个字母都有自己的意义,了解之后就不难记了:

    对于带字母p的函数:   如果参数中包含/,则将其视为路径名。 否则视为不带路径的程序名,在PATH环境变量的目录列表中搜索这个程序。

    函数名字中带字母 "l" 的表示其参数个数不确定,带字母 "v" 的表示使用字符串数组指针 argv 指向参数列表。
    函数名字中含有字母 "p" 的表示可以自动在环境变量 PATH 指定的路径中搜索要执行的程序。
    函数名字中含有字母 "e" 的函数比其它函数多一个参数 envp。该参数是字符串数组指针,用于指定环境变量。调用这样的函数时,可以由用户自行设定子进程的环境变量,存放在参数 envp 所指向的字符串数组中。

    简洁版:

        l 命令行参数列表

        p 搜素file时使用path变量

        v 使用命令行参数数组

        e 使用环境变量数组,不使用进程原有的环境变量,设置新加载程序运行的环境变量

     

    举例:

        char *const ps_argv[] ={"ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL};

        char *const ps_envp[] ={"PATH=/bin:/usr/bin", "TERM=console", NULL};   

        execl("/bin/ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL);    

        execv("/bin/ps",ps_argv);

        execle("/bin/ps","ps","-o","pid,ppid,pgrp,session,tpgid,comm",NULL,ps_envp);

        execve("/bin/ps",ps_argv,ps_envp);

        execlp("ps", "ps", "-o", "pid,ppid,pgrp,session,tpgid,comm", NULL);    //第一个是程序名,第二个是命令行参数

        execvp("ps", ps_argv);      

    上面说的app的父进程是bash ,我们在终端键入./app  是bash  fork一个新的进程,这个进程执行的代码时用exec执行我们键入的路径程序。

  • 相关阅读:
    五分钟带你了解啥是JWT
    软件系统方案设计
    基于工程实践的需求分析和概念原型
    Linux添加环境变量与GCC编译器添加INCLUDE与LIB环境变量
    ssh链接到minikube虚拟机
    error converting YAML to JSON: yaml: line 3: mapping values are not allowed in this context
    CentOS 7 virt-manager “authentication failed”错误及解决方法
    centos安装docker
    kali安装php-gd
    mariadb忘记root密码
  • 原文地址:https://www.cnblogs.com/Lune-Qiu/p/9267785.html
Copyright © 2011-2022 走看看