个性化阅读
专注于IT技术分析

fork()和exec()之间有什么区别?

每个应用程序(程序)都通过过程来执行, 处理是程序的运行实例。流程是通过不同的系统调用创建的, 最受欢迎的是fork()和exec()

fork()

pid_t pid = fork();

fork()通过复制调用过程来创建一个新过程, 该新过程称为子进程, 与父进程完全相同, 称为父进程, 但以下各项除外:

  1. 该子项具有其自己的唯一进程ID, 并且此PID与任何现有进程组的ID不匹配。
  2. 子级的父进程ID与父级的进程ID相同。
  3. 子级不会继承其父级的内存锁和信号量调整。
  4. 子级不会从其父级继承未完成的异步I / O操作, 也不会从其父级继承任何异步I / O上下文。

fork()的返回值

成功后, 将在父级中返回子进程的PID, 在子级中返回0。如果失败, 则在父级中返回-1, 不创建任何子级进程, 并适当设置errno。

有关fork系统调用的详细文章

exec()

exec()系列函数取代当前过程映像和新过程映像。它将程序加载到当前进程空间并从入口点运行它。

exec()系列包含以下功能, 我已经实现了execv()在下面的C程序中, 你可以尝试休息作为练习

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 execvpe(const char *file, char *const argv[], char *const envp[]);

fork vs exec

  • fork启动一个新进程, 该进程是调用它的进程的副本, 而exec用另一个(不同的)进程映像替换当前进程映像。
  • 在fork()的情况下, 父进程和子进程都同时执行, 而Control绝不会返回到原始程序, 除非有exec()错误。
//C program to illustrate  use of fork() &
//exec() system call for process creation
  
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h> 
#include <stdlib.h>
#include <errno.h>  
#include <sys/wait.h>
  
int main(){
    pid_t  pid;
    int ret = 1;
    int status;
    pid = fork();
  
    if (pid == -1){
  
       //pid == -1 means error occured
       printf ( "can't fork, error occured\n" );
       exit (EXIT_FAILURE);
    }
    else if (pid == 0){
  
       //pid == 0 means child process created
       //getpid() returns process id of calling process
       //Here It will return process id of child process
       printf ( "child process, pid = %u\n" , getpid());
       //Here It will return Parent of child Process means Parent process it self
       printf ( "parent of child process, pid = %u\n" , getppid()); 
  
       //the argv list first argument should point to  
       //filename associated with file being executed
       //the array pointer must be terminated by NULL 
       //pointer
       char * argv_list[] = { "ls" , "-lart" , "/home" , NULL};
  
       //the execv() only return if error occured.
       //The return value is -1
       execv( "ls" , argv_list);
       exit (0);
    }
    else {
       //a positive number is returned for the pid of
       //parent process
       //getppid() returns process id of parent of 
       //calling process
//Here It will return parent of parent process's ID
       printf ( "Parent Of parent process, pid = %u\n" , getppid());
       printf ( "parent process, pid = %u\n" , getpid()); 
  
         //the parent process calls waitpid() on the child
         //waitpid() system call suspends execution of 
         //calling process until a child specified by pid
         //argument has changed state
         //see wait() man page for all the flags or options
         //used here 
         if (waitpid(pid, &status, 0)> 0) {
              
             if (WIFEXITED(status) && !WEXITSTATUS(status)) 
               printf ( "program execution successful\n" );
              
             else if (WIFEXITED(status) && WEXITSTATUS(status)) {
                 if (WEXITSTATUS(status) == 127) {
  
                     //execv failed
                     printf ( "execv failed\n" );
                 }
                 else 
                     printf ( "program terminated normally, "
                        " but returned a non-zero status\n" );                
             }
             else 
                printf ( "program didn't terminate normally\n" );            
         } 
         else {
            //waitpid() failed
            printf ( "waitpid() failed\n" );
         }
       exit (0);
    }
    return 0;
}

输出如下:

parent process, pid = 11523
child process, pid = 14188
Program execution successful

参考文献:

Linux手册页

如果发现任何不正确的地方, 或者想分享有关上述主题的更多信息, 请写评论。

赞(0)
未经允许不得转载:srcmini » fork()和exec()之间有什么区别?

评论 抢沙发

评论前必须登录!