fork

pid_t fork(void);
  1. 它在调用进程(成为父进程)中返回一次,返回值为新派生进程(成为子进程)的进程ID号
  2. 在子进程中又返回一次,返回值为0.因此,返回值本身告知当前进程是子进程还是父进程

 fork在子进程中返回0而不是父进程的ID的原因:

  1. 任何子进程只有一个父进程,而且子进程总是可以通过调用getppid取得父进程的ID
  2. 父进程可以有许多子进程,而且无法获得各个子进程的进程ID。如果父进程想要跟踪所有子进程的ID,那么它必须记录每次调用fork的返回值。

  父进程中调用fork之前打开所有的描述字在fork返回之后由子进程分享。父进程调用accept之后调用fork。所接受的已连接的套接口随后就在父进程与子进程之间分享。通常情况下,子进程接着读和写这个套接口,父进程则关闭这个已连接套接口。
用法:

  1. 一个进程创建一个自身的拷贝,这样每个拷贝都可以在另一个拷贝执行其他任务的同时处理各自的某个操作。这是网络服务器的典型用法。
  2. 一个进程想要执行另一个程序。既然创建新进程的唯一方法为调用fork,该进程于是首先调用fork创建一个自身的拷贝,然后其中一个拷贝(通常为子进程)调用exec把自身替换成新的程序。这是诸如shell之类程序的典型用法。
  3. fork产生的子进程将继承父进程的信号掩码,但具有一个空的挂起信号集

exec

  存放在硬盘上的可执行文件能够被UNIX执行的唯一方法是:由一个现有进程调用六个exec函数中的某一个

  1. exec把当前进程映像替换成新的进程文件,而且该新程序通常从main函数处开始执行
  2. 进程ID并不改变
  3. 我们称调用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[]);

六个exec函数的区别

  1. 待执行的程序文件是由文件名还是由路径名指定
  2. 新程序的参数是一一列出还是由一个指针数组来引用
  3. 把调用进程的环境传递给新程序还是给新程序指定新的环境

  这些函数只在出错时才返回到调用者。否则,控制将传递给新程序的起始点,通常就是main函数。
这六个函数之间的关系如下图所示。一般来说,只有 execve 是内核中的系统调用,其他五个都是调用 execve 的库函数。

  1. 顶行三个函数把新程序的每个参数字符串指定成exec的一个独立参数,并以一个空指针结束可变数量的这些参数。底行三个函数都有一个作为exec参数的argv数组,其中含有指向新程序各个参数字符串的所有指针。既然没有指定参数字符串的数目,这个argv数组必须含有一个用于指定其末尾的空指针。
  2. 左列两个函数指定一个filename参数。exec将使用当前的PATH环境变量把该文件名参数转换为一个路径名。然而如果这两个函数的filename参数中不论何处含有一个斜杠(/),PAHT变量就不再使用。右两列四个函数指定一个全限定的pathname参数。
  3. 左两列四个函数不显式指定一个环境指针。相反,他们使用外部变量environ的当前值来构造一个传递给新程序的环境清单。右列两个函数显式指定一个环境清单,其envp指针数组必须以一个空指针结束。
    //execv
        int childpid;
        int i;
    
        )
        {
            //child process
            char * execv_str[] = {"echo", "executed by execv",NULL};
             )
            {
                perror("error on exec");
                exit();
            }
        }
        else
        {
            //parent process
            wait(&childpid);
            printf("execv done\n\n");
        }
    
    //execvp
        )
        {
            //child process
            char * execvp_str[] = {"echo", "executed by execvp",">>", "~/abc.txt",NULL};
             )
            {
                perror("error on exec");
                exit();
            }
        }
        else
        {
            //parent process
            wait(&childpid);
            printf("execvp done\n\n");
        }
    
    //execve
        )
        {
            //child process
            char * execve_str[] = {"env",NULL};
            char * env[] = {"PATH=/tmp", "USER=lei", "STATUS=testing", NULL};
             )
            {
                perror("error on exec");
                exit();
            }
        }
        else
        {
            //parent process
            wait(&childpid);
            printf("execve done\n\n");
        }
    
    //execl
        )
        {
            //child process
             )
            {
                perror("error on exec");
                exit();
            }
        }
        else
        {
            //parent process
            wait(&childpid);
            printf("execv done\n\n");
        }
    //execlp
        )
        {
            //child process
             )
            {
                perror("error on exec");
                exit();
            }
        }
        else
        {
            //parent process
            wait(&childpid);
            printf("execv done\n\n");
        }
    
    //execle
        )
        {
            //child process
            char * env[] = {"PATH=/home/gateman", "USER=lei", "STATUS=testing", NULL};
            ){
                perror("error on exec");
                exit();
            }
        }
        else
        {
            //parent process
            wait(&childpid);
            printf("execle done\n\n");
        }

fork和exec的更多相关文章

  1. 【转】Linux下Fork与Exec使用

    Linux下Fork与Exec使用 转自 Linux下Fork与Exec使用 一.引言 对于没有接触过Unix/Linux操作系统的人来说,fork是最难理解的概念之一:它执行一次却返回两个值.for ...

  2. Linux下Fork与Exec使用

    Linux下Fork与Exec使用   一.引言 对于没有接触过Unix/Linux操作系统的人来说,fork是最难理解的概念之一:它执行一次却返回两个值.fork函数是Unix系统最杰出的成就之一, ...

  3. linux进程之fork 和 exec函数

    ---恢复内容开始--- fork函数 该函数是unix中派生新进程的唯一方法. #include <unistd.h> pid_t   fork(void); 返回: (调用它一次, 它 ...

  4. linux c语言 fork() 和 exec 函数的简介和用法

    linux c语言 fork() 和 exec 函数的简介和用法   假如我们在编写1个c程序时想调用1个shell脚本或者执行1段 bash shell命令, 应该如何实现呢? 其实在<std ...

  5. Linux下Fork与Exec

    一.引言 对于没有接触过Unix/Linux操作系统的人来说,fork是最难理解的概念之一:它执行一次却返回两个值.fork函数是Unix系统最杰出的成就之一,它是七十年代UNIX早期的开发者经过长期 ...

  6. fork 和 exec

    https://blog.csdn.net/disadministrator/article/details/39347333 进程创建方法:fork.exec.clone,父进程等待子进程结束是用w ...

  7. fork、exec 和 exit 对 IPC 对象的影响

    GitHub: https://github.com/storagezhang Emai: debugzhang@163.com 华为云社区: https://bbs.huaweicloud.com/ ...

  8. Linux fork()、exec() Hook Risk、Design-Principle In Multi-Threadeed Program

    目录 . Linux exec指令执行监控Hook方案 . 在"Multi-Threadeed Program"环境中调用fork存在的风险 . Fork When Multi-T ...

  9. fork和exec一起使用

    先预览一下工程的目录树: 实现的功能:master进程启动slave进程. 看看Makefile内容: all: master.out slave.out master.out: master.cpp ...

  10. fork和exec函数

    #include<unistd.h> pid_t fork(void); 返回:在子进程中为0,在父进程中为子进程IO,若出错则为- fork最困难之处在于调用它一次,它却返回两次.它在调 ...

随机推荐

  1. hibernate查询oracle数据库表报错SQL state [null]; error code [17027]; 流已被关闭; nested exception is java.sql.SQLException: 流已被关闭

    把表字段类型 long 修改为 number类型即可

  2. fftshift函数详解

    reference: https://ww2.mathworks.cn/help/matlab/ref/fftshift.html 一.实信号情况 因为实信号以fs为采样速率的信号在 fs/2处混叠, ...

  3. Java实验2

    1.给定一组字符,编程输出里面数值最大者. package experiment; import java.util.Arrays; public class ShenYue { public sta ...

  4. IDEA中maven的依赖jar包报红

    问题描述: 查看本地的repository中有相关的jar包,但是在IDEA中就是报红(下面红色波浪线) 解决方法: 将pom.xml中相关的dependcy配置注释掉,maven中jar包就会删除. ...

  5. 类的无参方法和Doc注释

    一:Java Doc注释: 语法: /** *AccpSchool 类 *@author JadeBird *@version 1.0 2018/5/26 */ Java Doc是前Sun公司提供的一 ...

  6. Vuex的学习笔记一

    以下的解释,是在知乎看到的,感觉粗俗易懂. 组件之间的作用域独立,而组件之间经常又需要传递数据. A 为父组件,下面有子组件 B 和 C. A 的数据可以通过 props 传递给 B 和 C.A 可以 ...

  7. Vuejs 用$emit 与 $on 来进行兄弟组件之间的数据传输

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. json pickle xml shelve configparser

    json:# 是一种跨平台的数据格式 也属于序列化的一种方式pickle和shevle 序列化后得到的数据 只有python才可以解析通常企业开发不可能做一个单机程序 都需要联网进行计算机间的交互 J ...

  9. HTTP、TCP、IP、协议

    HTTP(HyperText Transfer Protocol) 即超文本传输协议,现在基本上所有web项目都遵从HTTP协议(协议就是一种人为的规范). 目前绝大部分使用的都是HTTP/1.1版本 ...

  10. Java 继承extends、关键字super和this、多态、动态绑定

    Manager 经理  extends Employee 雇员 "is-a"(是)关系是继承的一个明显特征.每个经理都是一名雇员. 从术语的角度讲,Manager是子类,Emplo ...